├── .github └── FUNDING.yml ├── .gitignore ├── .nvmrc ├── LICENSE.txt ├── README.md ├── build.sh ├── doc.md ├── examples ├── acorn-demo │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── util-new.js │ ├── util.js │ └── yarn.lock ├── demo-modules │ ├── commonjs │ │ ├── a.js │ │ ├── b.js │ │ └── index.js │ ├── esm-in-browser │ │ └── index.html │ └── esm │ │ ├── foo.mjs │ │ ├── lib.mjs │ │ └── my-app.mjs ├── gulp-and-webpack │ ├── client │ │ ├── common │ │ │ ├── css │ │ │ │ └── base.css │ │ │ └── js │ │ │ │ └── toast.js │ │ ├── explore │ │ │ └── index.html │ │ ├── home │ │ │ ├── index.css │ │ │ ├── index.html │ │ │ └── index.js │ │ ├── index.html │ │ ├── robots.txt │ │ ├── tree.txt │ │ └── user │ │ │ ├── index.css │ │ │ ├── index.html │ │ │ └── index.js │ ├── gulpfile-v1.js │ ├── gulpfile-v2.js │ ├── gulpfile-v3.js │ ├── gulpfile-v4.js │ ├── madge-app.js │ ├── package-lock.json │ ├── package.json │ ├── server │ │ └── index.js │ └── test.js ├── image-magick-cli │ └── test.jpg ├── less-demo │ ├── icons │ │ └── index.less │ ├── main.less │ └── output.css ├── my-react-app │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ └── manifest.json │ ├── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── components │ │ │ └── table.js │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ └── registerServiceWorker.js │ └── yarn.lock ├── node-demo │ └── 01-tcp │ │ ├── chat-room.js │ │ └── server.js ├── postcss-demo │ ├── package-lock.json │ ├── package.json │ └── profiler.js ├── react-demo │ ├── index.html │ └── package.json ├── sass-demo │ ├── icons │ │ ├── index.scss │ │ └── success.png │ ├── index.html │ ├── main.scss │ ├── output.css │ ├── output.css.map │ └── partials │ │ └── _reset.scss ├── static-file-server │ ├── .nvmrc │ ├── LICENSE │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── server │ │ ├── index.js │ │ └── pages │ │ │ └── react-ssr │ │ │ └── index.js │ └── static │ │ ├── amd-demo │ │ ├── index.css │ │ ├── index.html │ │ └── main.js │ │ ├── common.css │ │ ├── home │ │ ├── index.css │ │ ├── index.html │ │ └── index.js │ │ ├── html-import │ │ ├── index.html │ │ └── other.html │ │ ├── jquery-amd-clock │ │ ├── clock.js │ │ ├── index.css │ │ ├── index.html │ │ └── index.js │ │ ├── js │ │ ├── jquery-3.2.1.js │ │ ├── jquery-3.2.1.min.js │ │ ├── lodash.core.js │ │ ├── lodash.min.js │ │ └── require.js │ │ ├── react │ │ └── hello-world.html │ │ ├── utils │ │ ├── amd-lib-1.js │ │ └── time.js │ │ └── web-component │ │ ├── clock │ │ ├── index.css │ │ ├── index.html │ │ └── my-clock.js │ │ ├── shadow-dom │ │ ├── index.css │ │ ├── index.html │ │ ├── slot.html │ │ ├── template-2.html │ │ └── template.html │ │ ├── word-count │ │ ├── index.html │ │ └── main.js │ │ └── x-image │ │ ├── app.html │ │ └── x-image.html ├── uglify-js-demo │ ├── package-lock.json │ ├── package.json │ ├── use-acorn.js │ └── use-uglify.js ├── vcs-history │ └── 千辛万苦毕业论文 │ │ ├── 毕业论文-v2.txt │ │ ├── 毕业论文-v20.txt │ │ ├── 毕业论文-v3.txt │ │ ├── 毕业论文-v4.txt │ │ ├── 毕业论文-最终版-再也不改了.txt │ │ ├── 毕业论文-最终版-我发誓这个才是最终版.txt │ │ ├── 毕业论文-最终版-还是改了一下.txt │ │ ├── 毕业论文-最终版-这个是最终版.txt │ │ ├── 毕业论文-最终版.txt │ │ └── 毕业论文.txt ├── vue-demo │ ├── my-project │ │ ├── .babelrc │ │ ├── .editorconfig │ │ ├── .eslintignore │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .postcssrc.js │ │ ├── README.md │ │ ├── config │ │ │ ├── dev.env.js │ │ │ ├── index.js │ │ │ └── prod.env.js │ │ ├── index.html │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── App.vue │ │ │ ├── assets │ │ │ │ └── logo.png │ │ │ ├── components │ │ │ │ └── HelloWorld.vue │ │ │ └── main.js │ │ └── static │ │ │ └── .gitkeep │ ├── tax-calc │ │ ├── index.css │ │ ├── index.html │ │ ├── index.js │ │ └── screenshot.png │ ├── vue-build │ │ ├── .cache │ │ │ ├── explore.js │ │ │ ├── home.js │ │ │ └── user.followers.js │ │ ├── .eslintrc.js │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── readme.md │ │ ├── src │ │ │ ├── index.html │ │ │ ├── pages │ │ │ │ ├── explore │ │ │ │ │ └── index.vue │ │ │ │ ├── home │ │ │ │ │ └── index.vue │ │ │ │ └── user │ │ │ │ │ └── followers │ │ │ │ │ └── index.vue │ │ │ └── vue-template.js │ │ └── webpack.config.js │ └── vue-v2.5.16.js └── webpack-mpa │ ├── .nvmrc │ ├── README.md │ ├── client │ ├── components │ │ └── layout │ │ │ ├── base-page.jsx │ │ │ └── page.js │ ├── index.html │ └── pages │ │ ├── explore │ │ ├── index.jsx │ │ └── style.less │ │ ├── home │ │ ├── index.jsx │ │ └── style.less │ │ └── user │ │ └── index.jsx │ ├── nodemon.json │ ├── package.json │ ├── server │ ├── index.js │ ├── middlewares │ │ └── render.js │ └── utils │ │ └── get-entry.js │ └── webpack.config.js ├── package.json ├── scripts └── pre-commit.sh ├── src ├── README.md ├── book.json ├── js │ └── index.js ├── package-lock.json ├── part-0 │ ├── 0-cover.md │ ├── 1-about-author.md │ └── 2-pre.md ├── part-1 │ ├── chapter-1-intro │ │ └── 1-web前端简史.md │ ├── chapter-2-http │ │ ├── 1-http.md │ │ ├── 2-http-servers.md │ │ ├── 3-http-proxies.md │ │ └── index.md │ ├── chapter-3-js │ │ ├── 01-language-features.md │ │ ├── 02-js-engine.md │ │ ├── 03-js-future.md │ │ └── index.md │ ├── chapter-4-webfe-apps │ │ └── index.md │ ├── chapter-5-nodejs │ │ ├── 01-nodejs.md │ │ ├── 02-npm.md │ │ ├── 03-yarn.md │ │ └── index.md │ ├── chapter-html │ │ └── index.md │ ├── images │ │ ├── coffeescript-logo.png │ │ ├── dynamic_page_en.png │ │ ├── emacs-logo.png │ │ ├── homebrew-logo.png │ │ ├── homebrew.png │ │ ├── http-3-types.png │ │ ├── http-client-and-server.png │ │ ├── http-requests-trends.png │ │ ├── http-version-history.png │ │ ├── iterm2-autocomplete.png │ │ ├── iterm2-hotkey.png │ │ ├── iterm2-logo.png │ │ ├── iterm2-multi-panes.png │ │ ├── javascript-timeline.png │ │ ├── js-origin.png │ │ ├── kernel_layout.png │ │ ├── logo2x.psd │ │ ├── mvc-process.png │ │ ├── node_modules_vs_black_holes.jpg │ │ ├── nodejs-logo.png │ │ ├── npm-view-01.png │ │ ├── oh-my-zsh-01.png │ │ ├── os-windows1.0.png │ │ ├── sublime-01-logo.png │ │ ├── three-os-logos.png │ │ ├── vim-logo.png │ │ ├── vim-logo.svg │ │ ├── vscode-debug-node-1.png │ │ ├── vscode-shell-command.png │ │ ├── web-history-1-static.png │ │ └── yarn-logo.png │ ├── index.md │ ├── welcome-on-board │ │ ├── 1-computer-and-os.md │ │ ├── 2-terminals.md │ │ ├── 3-node-and-npm.md │ │ ├── 4-code-editors.md │ │ └── index.md │ └── 示例清单.md ├── part-2 │ ├── art-about-code.md │ ├── chapter-0-git-and-vcs │ │ ├── 01-using-git.md │ │ ├── 02-git-hooks.md │ │ ├── 03-git-workflow.md │ │ ├── 04-server-side-git.md │ │ ├── images │ │ │ ├── centr-decentr.png │ │ │ ├── chinese-char-2.png │ │ │ ├── chinese-char.png │ │ │ ├── git-3-areas.png │ │ │ ├── git-logo.png │ │ │ ├── local-vcs-demo.png │ │ │ └── local-vcs.png │ │ └── index.md │ ├── chapter-1-模块系统 │ │ ├── images │ │ │ ├── hatton-2-repaint.png │ │ │ ├── hatton.png │ │ │ ├── js-module-too-small.png │ │ │ └── require-js-effect.png │ │ ├── section-1-概述.md │ │ ├── section-2-刀耕火种时代.md │ │ ├── section-3-common-js.md │ │ ├── section-4-amd.md │ │ ├── section-5-umd.md │ │ └── section-6-esm.md │ ├── chapter-2-前端资源构建 │ │ ├── 03-img-processing.md │ │ ├── 04-gulp.md │ │ ├── 05-webpack.md │ │ ├── 06-practice-usage.md │ │ ├── images │ │ │ ├── apng-assembler-logo.png │ │ │ ├── base64-encode-example.png │ │ │ ├── base64-index-table.png │ │ │ ├── build-tools-usage.png │ │ │ ├── dir-01-build.png │ │ │ ├── dir-01-client-to-build.png │ │ │ ├── dir-01-client.png │ │ │ ├── dir-02-home.png │ │ │ ├── edge-webp-progress.png │ │ │ ├── gimp-logo-wilber-big.png │ │ │ ├── gimp-ui.jpg │ │ │ ├── gulp-2x.png │ │ │ ├── http-cache.png │ │ │ ├── image-caniuse-webp.png │ │ │ ├── image-file-formats.jpg │ │ │ ├── image-optim-app@2x.png │ │ │ ├── image-optim-logo.png │ │ │ ├── imagemagick-logo-wizard.jpg │ │ │ ├── interlace-demo.png │ │ │ ├── result-home-01.png │ │ │ ├── webpack-logo.png │ │ │ └── webpack-logo.svg │ │ ├── index.md │ │ └── mp-building.md │ ├── chapter-3-js-parsers │ │ ├── 1-js-parser.md │ │ ├── 2-babel.md │ │ ├── 3-eslint.md │ │ ├── images │ │ │ ├── ast-01.png │ │ │ ├── babel-01.jpg │ │ │ ├── babel-02.png │ │ │ ├── eslint-sublime-01.png │ │ │ ├── eslint-vscode.png │ │ │ ├── parsing-process.png │ │ │ └── tower-of-babel.jpg │ │ └── index.md │ ├── chapter-4-css-processors │ │ ├── 01-css-processors.md │ │ ├── 02-postcss.md │ │ ├── images │ │ │ ├── autoprefixer-logo.png │ │ │ ├── css-preprocessors-usage.png │ │ │ ├── four-mostly-used-css-preprocessors.png │ │ │ ├── resolve-url-loader-demo-1.png │ │ │ └── sass-logo.png │ │ └── index.md │ ├── chapter-5-debug │ │ ├── 1-browser-debug.md │ │ ├── 2-xcode-simulator.md │ │ ├── 3-nodejs-debug.md │ │ ├── 4-mobile-web-debug.md │ │ ├── 5-http-proxy.md │ │ ├── 6-http-client.md │ │ ├── images │ │ │ ├── chrome-copy-as-curl.jpg │ │ │ ├── eruda.jpg │ │ │ ├── node-debug-01.png │ │ │ ├── node-debug-02.png │ │ │ ├── node-debug-03.png │ │ │ ├── safari-debug.png │ │ │ ├── simulator-1.png │ │ │ ├── simulator-install.png │ │ │ ├── switchy-omega-01.png │ │ │ ├── webview-debug-01.jpg │ │ │ ├── webview-debug-02.jpg │ │ │ ├── webview-debug-03.jpg │ │ │ └── webview-debug-04-wechat.png │ │ └── index.md │ ├── chapter-5-服务端运维.md │ ├── chapter-6-test │ │ ├── 01-unit-test.md │ │ ├── 02-browser-compatibility.md │ │ ├── 03-components-test.md │ │ └── index.md │ └── index.md ├── part-3 │ ├── article-2.md │ ├── chapter-2-amd-jquery │ │ └── index.md │ ├── chapter-3-web-components │ │ ├── article-1-custom-elements.md │ │ ├── article-2-shadow-dom.md │ │ ├── article-3-template.md │ │ ├── article-4-html-import.md │ │ ├── images │ │ │ ├── clock-text.png │ │ │ ├── import-demo-1.png │ │ │ ├── import-demo-2.png │ │ │ ├── input-shadow-dom.png │ │ │ ├── shadow-dom.png │ │ │ └── template-2.jpg │ │ └── index.md │ ├── chapter-4-polymer │ │ └── index.md │ ├── chapter-5-react │ │ ├── 1-get-started.md │ │ ├── 2-virtual-dom.md │ │ ├── 3-message-among-components.md │ │ ├── 4-ssr.md │ │ ├── 5-react-and-fp.md │ │ ├── 6-hook.md │ │ ├── images │ │ │ └── react-ssr.png │ │ └── index.md │ ├── chapter-6-vue │ │ ├── 1-basic-demo.md │ │ ├── 2-vue-concepts-and-priciples.md │ │ ├── 3-single-file-components.md │ │ ├── 4-build-vue.md │ │ ├── index.md │ │ ├── tax-calculator-2.png │ │ ├── tax-calculator.png │ │ └── vue-logo.png │ ├── chapter-7-miniprogram │ │ └── index.md │ └── index.md ├── part-4 │ ├── 01-标准库.md │ ├── 02-编码规范.md │ ├── 03-重构.md │ ├── 04-fe-self-learning.md │ ├── images │ │ └── comfort-zone.png │ └── index.md ├── part-5 │ ├── 02-about-web-browsers.md │ ├── 03-lambda-calculus.md │ ├── 04-immutable-data.md │ ├── about-writing-this-book.md │ ├── images │ │ └── calibre-logo.png │ ├── index.md │ └── promise-polyfill.js ├── part-6-ref │ └── index.md ├── styles │ └── common.css ├── summary.md └── tmp │ └── 读书摘记.md ├── yarn.lock └── 写作排期计划.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [zilong-thu] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: https://borninsummer.com/donate/ 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | node_modules 4 | 5 | *.log 6 | 7 | build 8 | 9 | _book -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v9.7.0 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Web前端工程化与组件化开发实践 2 | 3 | 英文名:Practice in Front End Engineering and Components Development 4 | 5 | ## 在线阅读地址 6 | 7 | [https://borninsummer.com/Practice-in-Front-End-Engineering-and-Components-Development/](https://borninsummer.com/Practice-in-Front-End-Engineering-and-Components-Development/) 8 | 9 | ## Github 地址 10 | 11 | 书籍的原始内容托管在 [Github](https://github.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development)。 12 | 13 | ## License & Copyright 14 | 15 | 本书采用[署名-非商业性使用-禁止演绎 4.0 国际](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh)协议进行开源写作。 16 | 17 | © 2017-2021 王子龙 18 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gitbook build src _book; 4 | 5 | git checkout gh-pages; 6 | 7 | cp -r _book/* . 8 | 9 | git add --all; 10 | 11 | git commit -m 'publish book'; 12 | 13 | git push origin gh-pages -f; 14 | 15 | git checkout master; 16 | -------------------------------------------------------------------------------- /doc.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/doc.md -------------------------------------------------------------------------------- /examples/acorn-demo/app.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const {Parser} = require('acorn'); 3 | const walk = require('acorn-walk'); 4 | const escodegen = require('escodegen'); 5 | 6 | console.log(JSON.stringify(Parser.parse('const a = 1;'))); 7 | 8 | // 读取 util.js 里的文件内容 9 | const fileContent = fs.readFileSync('./util.js'); 10 | // 生成抽象语法树 11 | const ast = Parser.parse(fileContent, { 12 | // 注意这里指定了源内容的类型为 module,即模块 13 | sourceType: 'module' 14 | }); 15 | 16 | 17 | // 定义访问者函数 18 | const visitors = { 19 | // 会在每次遇到一个 type 为 ExportNamedDeclaration 的节点时执行此函数 20 | ExportNamedDeclaration(node) { 21 | if (node.declaration.type === 'FunctionDeclaration') { 22 | console.log(`找到了一个 export 函数的语句,函数名称是:${node.declaration.id.name}`); 23 | node.declaration.id.name = '$' + node.declaration.id.name; 24 | } 25 | } 26 | }; 27 | // 遍历抽象语法树 28 | walk.simple(ast, visitors); 29 | 30 | fs.writeFileSync('util-new.js', escodegen.generate(ast, { 31 | format: { 32 | // 指定输出代码的缩进为两个空格 33 | indent: { 34 | style: ' ', 35 | } 36 | } 37 | })); 38 | -------------------------------------------------------------------------------- /examples/acorn-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "acorn-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "acorn": "^6.4.1", 13 | "acorn-walk": "^6.0.1", 14 | "escodegen": "^1.11.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/acorn-demo/util-new.js: -------------------------------------------------------------------------------- 1 | export function $queryData() { 2 | return []; 3 | } 4 | export function $addData(data) { 5 | return true; 6 | } 7 | export function $updateData(data) { 8 | return true; 9 | } 10 | export function $removeData(id) { 11 | return true; 12 | } -------------------------------------------------------------------------------- /examples/acorn-demo/util.js: -------------------------------------------------------------------------------- 1 | export function queryData() { 2 | return []; 3 | } 4 | 5 | export function addData(data) { 6 | return true; 7 | } 8 | 9 | export function updateData(data) { 10 | return true; 11 | } 12 | 13 | export function removeData(id) { 14 | return true; 15 | } 16 | -------------------------------------------------------------------------------- /examples/demo-modules/commonjs/a.js: -------------------------------------------------------------------------------- 1 | var b = require('./b.js'); 2 | b.name = 'bb'; 3 | 4 | 5 | module.exports = function(x, y) { 6 | return x + y; 7 | } 8 | 9 | console.log('a is loaded.'); 10 | -------------------------------------------------------------------------------- /examples/demo-modules/commonjs/b.js: -------------------------------------------------------------------------------- 1 | exports.name = 'b'; 2 | 3 | console.log('b is loaded.'); 4 | 5 | exports.age = 29; 6 | 7 | exports.time = new Date(); 8 | -------------------------------------------------------------------------------- /examples/demo-modules/commonjs/index.js: -------------------------------------------------------------------------------- 1 | var b1 = require('./b.js'); 2 | var a = require('./a.js'); 3 | var b2 = require('./b.js'); 4 | 5 | console.log('b1 === b2 => ', b1 === b2); 6 | 7 | console.log(b1); 8 | 9 | console.log(module); 10 | -------------------------------------------------------------------------------- /examples/demo-modules/esm-in-browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/demo-modules/esm/foo.mjs: -------------------------------------------------------------------------------- 1 | console.log('I am foo'); 2 | 3 | -------------------------------------------------------------------------------- /examples/demo-modules/esm/lib.mjs: -------------------------------------------------------------------------------- 1 | 2 | console.log('lib module is loaded into memory.'); 3 | 4 | export var name = '阿珂'; 5 | 6 | export function setName(n) { 7 | name = n; 8 | } 9 | 10 | export function add(x, y) { 11 | return x + y; 12 | } -------------------------------------------------------------------------------- /examples/demo-modules/esm/my-app.mjs: -------------------------------------------------------------------------------- 1 | import {name} from './lib.mjs'; 2 | import {setName, add} from './lib.mjs'; 3 | 4 | import './foo?query=1'; 5 | import './foo?query=2'; 6 | 7 | console.log(name); 8 | setName('李白'); 9 | console.log(name); 10 | 11 | console.log('sum: ' + add(2, 3)); 12 | 13 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/common/css/base.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/common/js/toast.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/gulp-and-webpack/client/common/js/toast.js -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/explore/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Explore 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/home/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 14px; 3 | } 4 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/home/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Home Page 5 | 6 | 7 | 8 | 9 | 10 |

测试 ESM 组织源码及使用 webpack 打包 JS 代码

11 |

12 |   
13 | 
14 | 
15 | 


--------------------------------------------------------------------------------
/examples/gulp-and-webpack/client/home/index.js:
--------------------------------------------------------------------------------
 1 | import _ from 'underscore';
 2 | import toast from 'toast2';
 3 | 
 4 | var str = 'Hello World.';
 5 | console.log(str);
 6 | 
 7 | // 调用 underscore 方法
 8 | var pickedData = _.pick({name: 'moe', age: 50, userid: 'moe1'}, ['name', 'age']);
 9 | console.log('pickedData: ', pickedData);
10 | 
11 | document.querySelector('#output').innerHTML = '=> ' + JSON.stringify(pickedData);
12 | 


--------------------------------------------------------------------------------
/examples/gulp-and-webpack/client/index.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |   
 5 | 
 6 | 
 7 |   

导航

8 | 16 | 17 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/tree.txt: -------------------------------------------------------------------------------- 1 | . 2 | ├── common 3 | │   ├── css 4 | │   │   └── base.css 5 | │   ├── docs 6 | │   ├── images 7 | │   └── js 8 | │   └── toast.js 9 | ├── explore 10 | │   └── index.html 11 | ├── home 12 | │   ├── index.css 13 | │   ├── index.html 14 | │   └── index.js 15 | ├── index.html 16 | ├── robots.txt 17 | ├── tree.txt 18 | └── user 19 | ├── index.html 20 | └── index.js 21 | 22 | 8 directories, 11 files 23 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/user/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/user/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | User 5 | 6 | 7 |

User Page

8 | 9 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/client/user/index.js: -------------------------------------------------------------------------------- 1 | import './index.css'; 2 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/gulpfile-v1.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const glob = require('glob'); 4 | const gulp = require('gulp'); 5 | const copydir = require('copy-dir'); 6 | 7 | 8 | const BUILD_ROOT = './build/'; 9 | const SRC_ROOT = './client'; 10 | 11 | gulp.task('build-client', function() { 12 | console.time('build-client'); 13 | copydir.sync(SRC_ROOT, BUILD_ROOT); 14 | console.timeEnd('build-client'); 15 | }); 16 | 17 | gulp.task('watch', () => { 18 | gulp.watch(['./client/**/*'], ['build-client']); 19 | }); 20 | 21 | gulp.task('default', ['build-client', 'watch']); 22 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/gulpfile-v2.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const glob = require('glob'); 4 | const gulp = require('gulp'); 5 | const fse = require('fs-extra'); 6 | const copydir = require('copy-dir'); 7 | const cleanCSS = require('gulp-clean-css'); 8 | const uglify = require('gulp-uglify'); 9 | 10 | const BUILD_ROOT = './build/'; 11 | const SRC_ROOT = './client'; 12 | 13 | gulp.task('css', () => { 14 | return gulp.src(`${SRC_ROOT}/**/*.css`) 15 | .pipe(cleanCSS()) 16 | .pipe(gulp.dest(BUILD_ROOT)); 17 | }); 18 | 19 | gulp.task('js', () => { 20 | return gulp.src(`${SRC_ROOT}/**/*.js`) 21 | .pipe(uglify()) 22 | .pipe(gulp.dest(BUILD_ROOT)); 23 | }); 24 | 25 | gulp.task('copy', () => { 26 | const files = glob.sync(`${SRC_ROOT}/**/*.!(js|css)`); 27 | files.forEach(item => { 28 | fse.copySync(item, item.replace(SRC_ROOT, BUILD_ROOT)); 29 | }); 30 | }); 31 | 32 | gulp.task('watch', () => { 33 | gulp.watch(['./client/**/*.css'], ['css']); 34 | gulp.watch(['./client/**/*.js'], ['js']); 35 | gulp.watch(['./client/**/*.!(js|css)'], ['copy']); 36 | }); 37 | 38 | gulp.task('default', ['css', 'js', 'copy', 'watch']); 39 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/gulpfile-v3.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const glob = require('glob'); 4 | const gulp = require('gulp'); 5 | const fse = require('fs-extra'); 6 | const webpack = require('webpack'); 7 | const copydir = require('copy-dir'); 8 | const cleanCSS = require('gulp-clean-css'); 9 | const uglify = require('gulp-uglify'); 10 | const gulpLess = require('gulp-less'); 11 | 12 | 13 | const BUILD_ROOT = './build/'; 14 | const SRC_ROOT = './client'; 15 | 16 | gulp.task('css', () => { 17 | return gulp.src(`${SRC_ROOT}/**/*.css`) 18 | .pipe(gulpLess()) 19 | .pipe(cleanCSS()) 20 | .pipe(gulp.dest(BUILD_ROOT)); 21 | }); 22 | 23 | 24 | // 找到所有的 index.js 文件 25 | function findAllJSEntryFiles() { 26 | const files = glob 27 | .sync('./client/**/index.js') 28 | .map(item => ({ 29 | path: item, 30 | name: item.replace('./client/', '').replace('.js', ''), 31 | })); 32 | 33 | const pagesJsEntry = {}; 34 | files.forEach(item => { 35 | // pagesJsEntry 形如 { 36 | // 'home/index': './client/home/index.js' 37 | // } 38 | pagesJsEntry[item.name] = item.path; 39 | }); 40 | 41 | return pagesJsEntry; 42 | } 43 | 44 | gulp.task('js', () => { 45 | const conf = { 46 | entry: findAllJSEntryFiles(), 47 | output: { 48 | filename: '[name].js', 49 | path: path.resolve(__dirname, 'build'), 50 | } 51 | }; 52 | 53 | webpack(conf, (err, stats) => { 54 | if (err || stats.hasErrors()) { 55 | console.log('-- error --'); 56 | return; 57 | } 58 | 59 | // Done processing 60 | console.log('\nwebpack 构建完成 ✔\n'); 61 | }); 62 | }); 63 | 64 | gulp.task('copy', () => { 65 | const files = glob.sync(`${SRC_ROOT}/**/*.!(js|css)`); 66 | files.forEach(item => { 67 | fse.copySync(item, item.replace(SRC_ROOT, BUILD_ROOT)); 68 | }); 69 | }); 70 | 71 | gulp.task('watch', () => { 72 | gulp.watch(['./client/**/*.css'], ['css']); 73 | gulp.watch(['./client/**/*.js'], ['js']); 74 | gulp.watch(['./client/**/*.!(js|css)'], ['copy']); 75 | }); 76 | 77 | gulp.task('default', ['css', 'js', 'copy', 'watch']); 78 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/madge-app.js: -------------------------------------------------------------------------------- 1 | const madge = require('madge'); 2 | 3 | madge('./client/home/index.js').then((res) => { 4 | console.log(res.obj()); 5 | }); 6 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-and-webpack", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "static": "node ./server/index.js", 9 | "build-v1": "gulp --gulpfile ./gulpfile-v1.js", 10 | "build-v2": "gulp --gulpfile ./gulpfile-v2.js", 11 | "build-v3": "gulp --gulpfile ./gulpfile-v3.js", 12 | "build-v4": "gulp --gulpfile ./gulpfile-v4.js" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "copy-dir": "^0.3.0", 18 | "fs-extra": "^5.0.0", 19 | "gulp": "^3.9.1", 20 | "gulp-clean-css": "^3.9.3", 21 | "gulp-less": "^4.0.0", 22 | "gulp-uglify": "^3.0.0", 23 | "less": "^3.0.1", 24 | "webpack": "^4.12.2" 25 | }, 26 | "dependencies": { 27 | "acorn": "^5.7.4", 28 | "css-loader": "^0.28.11", 29 | "jquery": "^3.3.1", 30 | "koa": "^2.5.0", 31 | "koa-static": "^4.0.2", 32 | "lodash": "^4.17.5", 33 | "madge": "^3.0.1", 34 | "style-loader": "^0.21.0", 35 | "toast2": "^2.1.0", 36 | "uglify-js": "^3.3.20", 37 | "underscore": "^1.8.3", 38 | "zepto": "^1.2.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/server/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const Koa = require('koa'); 3 | const app = new Koa(); 4 | const serve = require('koa-static'); 5 | 6 | 7 | app.use(async (ctx, next) => { 8 | const start = Date.now(); 9 | await next(); 10 | const ms = Date.now() - start; 11 | console.log(`${ctx.method} ${ctx.url} - ${ms}`); 12 | }); 13 | 14 | // 静态文件服务目录 15 | const staticDir = path.join(__dirname, '../build'); 16 | app.use(serve(staticDir, { 17 | maxage: 360000, 18 | })); 19 | 20 | const port = 9001; 21 | app.listen(port); 22 | console.log(`静态文件服务已启动: \nhttp://localhost:${port}`); 23 | -------------------------------------------------------------------------------- /examples/gulp-and-webpack/test.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'); 2 | 3 | 4 | 5 | const input = 'I love cupcakes'; 6 | 7 | const secret = 'abcdefg'; 8 | const NUM = 1; 9 | console.time('sha256'); 10 | for (var i = 0; i < NUM; i++) { 11 | const hash = crypto.createHash('sha256') 12 | .update(input) 13 | .digest('hex'); 14 | } 15 | console.timeEnd('sha256'); 16 | 17 | 18 | console.time('md5'); 19 | for (var i = 0; i < NUM; i++) { 20 | const hash = crypto.createHash('md5') 21 | .update(input) 22 | .digest('hex'); 23 | } 24 | console.timeEnd('md5'); 25 | -------------------------------------------------------------------------------- /examples/image-magick-cli/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/image-magick-cli/test.jpg -------------------------------------------------------------------------------- /examples/less-demo/icons/index.less: -------------------------------------------------------------------------------- 1 | .my-icon { 2 | display: inline-block; 3 | height: 1em; 4 | width: 1em; 5 | } 6 | 7 | .my-icon-success { 8 | background-image: url(./success.png); 9 | } -------------------------------------------------------------------------------- /examples/less-demo/main.less: -------------------------------------------------------------------------------- 1 | @import "./icons/index.less"; 2 | -------------------------------------------------------------------------------- /examples/less-demo/output.css: -------------------------------------------------------------------------------- 1 | .my-icon { 2 | display: inline-block; 3 | height: 1em; 4 | width: 1em; 5 | } 6 | .my-icon-success { 7 | background-image: url(./success.png); 8 | } 9 | -------------------------------------------------------------------------------- /examples/my-react-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /examples/my-react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-react-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^16.3.2", 7 | "react-dom": "^16.3.2", 8 | "react-scripts": "1.1.4" 9 | }, 10 | "scripts": { 11 | "start": "react-scripts start", 12 | "build": "react-scripts build", 13 | "test": "react-scripts test --env=jsdom", 14 | "eject": "react-scripts eject" 15 | } 16 | } -------------------------------------------------------------------------------- /examples/my-react-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/my-react-app/public/favicon.ico -------------------------------------------------------------------------------- /examples/my-react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /examples/my-react-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /examples/my-react-app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /examples/my-react-app/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | logo 11 |

Welcome to React

12 |
13 |

14 | To get started, edit src/App.js and save to reload. 15 |

16 |
17 | ); 18 | } 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /examples/my-react-app/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/my-react-app/src/components/table.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/my-react-app/src/components/table.js -------------------------------------------------------------------------------- /examples/my-react-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /examples/my-react-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import registerServiceWorker from './registerServiceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | registerServiceWorker(); 9 | -------------------------------------------------------------------------------- /examples/my-react-app/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/node-demo/01-tcp/chat-room.js: -------------------------------------------------------------------------------- 1 | var net = require("net"); 2 | var clients = []; 3 | net.createServer(function(sock){ 4 | clients.push(sock); 5 | sock.on("data", function(data) { 6 | for (var i=0; i str2.length) { 9 | return 1; 10 | } 11 | return 0; 12 | } 13 | 14 | module.exports = postcss.plugin('profiler', function profiler(options) { 15 | 16 | return function (css) { 17 | 18 | options = options || {}; 19 | 20 | var rulesBuild = []; 21 | var rulesBuildDistinguished = []; 22 | 23 | // Processing code will be added here 24 | css.walkRules(function (rule) { 25 | var selector = rule.selector; 26 | rulesBuild.push(selector); 27 | 28 | var selectorArr = selector.split(',').map(item => String(item).trim()); 29 | rulesBuildDistinguished = rulesBuildDistinguished.concat(selectorArr); 30 | // rule.walkDecls(function (decl, index) { 31 | // console.log(' - ', decl.prop, ': ', decl.value); 32 | // }); 33 | }); 34 | 35 | rulesBuild.sort(compare); 36 | 37 | // 选择器名按照字符串长度升序排序 38 | rulesBuildDistinguished.sort(compare).reverse(); 39 | 40 | var totalRulesCount = rulesBuild.length; 41 | console.info('There are totaly ', colors.bold(totalRulesCount), ' rules after build.'); 42 | 43 | var duplicatedRulesObj = {}; 44 | var rulesWithLongName = []; 45 | 46 | // 找出重复声明了的选择器(含逗号) 47 | for (var i = 0; i < totalRulesCount; i++) { 48 | for (var j = i + 1; j < totalRulesCount; j++) { 49 | if (rulesBuild[i] === rulesBuild[j]) { 50 | duplicatedRulesObj[rulesBuild[i]] = true; 51 | } 52 | } 53 | } 54 | 55 | var duplicatedRulesArr = Object.keys(duplicatedRulesObj); 56 | var SPLIT_LINE = colors.grey('---------------------------------------------'); 57 | console.log('==== CSS Static Analysis Report ===='); 58 | console.log(SPLIT_LINE); 59 | console.log('Duplicated rules: ', colors.bold(duplicatedRulesArr.length)); 60 | console.log(SPLIT_LINE); 61 | duplicatedRulesArr.forEach(item => { 62 | console.log(' ', item); 63 | }); 64 | console.log(SPLIT_LINE); 65 | var LONG_NAME_OUTPUT_COUNT = 10; 66 | console.log(`Rules with long name, TOP ${colors.bold(LONG_NAME_OUTPUT_COUNT)}: `); 67 | console.log(SPLIT_LINE); 68 | // 找出过长的选择器名(已考虑逗号分隔),前 10 个即可 69 | for (var i = 0; i < LONG_NAME_OUTPUT_COUNT; i++) { 70 | console.log(` [${i+1}] `, rulesBuildDistinguished[i]); 71 | } 72 | console.log('\n==== END CSS Static Analysis Report ====\n'); 73 | } 74 | 75 | }); -------------------------------------------------------------------------------- /examples/react-demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World 6 | 7 | 8 | 9 | 10 | 11 |
12 | 20 | 32 | 33 | -------------------------------------------------------------------------------- /examples/react-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /examples/sass-demo/icons/index.scss: -------------------------------------------------------------------------------- 1 | .my-icon { 2 | display: inline-block; 3 | height: 1em; 4 | width: 1em; 5 | } 6 | 7 | .my-icon-success { 8 | background-image: url(./success.png); 9 | } -------------------------------------------------------------------------------- /examples/sass-demo/icons/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/sass-demo/icons/success.png -------------------------------------------------------------------------------- /examples/sass-demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | sass demo 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 | 13 | -------------------------------------------------------------------------------- /examples/sass-demo/main.scss: -------------------------------------------------------------------------------- 1 | @import "./partials/_reset.scss"; 2 | @import "./icons/index.scss"; 3 | 4 | html { 5 | font-size: 100px; 6 | } 7 | .navbar { 8 | font-size: .14rem; 9 | .logo { 10 | display: inline-block; 11 | height: .5rem; 12 | width: .5rem; 13 | } 14 | 15 | button { 16 | border-radius: .02rem; 17 | transition: box-shadow .2s; 18 | &:hover { 19 | box-shadow: 0 0 5px rgba(0, 0, 0, .2); 20 | } 21 | } 22 | } 23 | 24 | $font-stack: Helvetica, sans-serif; 25 | $primary-color: #333; 26 | 27 | body { 28 | font: 100% $font-stack; 29 | color: $primary-color; 30 | padding: .3rem; 31 | } 32 | 33 | 34 | // mixins 35 | @mixin transform($property) { 36 | -webkit-transform: $property; 37 | -ms-transform: $property; 38 | transform: $property; 39 | } 40 | 41 | .box { @include transform(rotate(30deg)); } 42 | 43 | 44 | @mixin keyframes($animationName) { 45 | @-webkit-keyframes #{$animationName} { 46 | @content; 47 | } 48 | @-ms-keyframes #{$animationName} { 49 | @content; 50 | } 51 | @keyframes #{$animationName} { 52 | @content; 53 | } 54 | } 55 | 56 | @include keyframes(spinning360) { 57 | 0% { 58 | transform: rotateZ(0deg); 59 | } 60 | 100% { 61 | transform: rotateZ(360deg); 62 | } 63 | } 64 | 65 | .spinning { 66 | display: inline-block; 67 | height: 1em; 68 | width: 1em; 69 | border-radius: 10%; 70 | border: 1px solid #ccc; 71 | animation: spinning360 3s infinite linear; 72 | } 73 | -------------------------------------------------------------------------------- /examples/sass-demo/output.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | .my-icon { 8 | display: inline-block; 9 | height: 1em; 10 | width: 1em; 11 | } 12 | 13 | .my-icon-success { 14 | background-image: url(./success.png); 15 | } 16 | 17 | html { 18 | font-size: 100px; 19 | } 20 | 21 | .navbar { 22 | font-size: 0.14rem; 23 | } 24 | .navbar .logo { 25 | display: inline-block; 26 | height: 0.5rem; 27 | width: 0.5rem; 28 | } 29 | .navbar button { 30 | border-radius: 0.02rem; 31 | transition: box-shadow 0.2s; 32 | } 33 | .navbar button:hover { 34 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); 35 | } 36 | 37 | body { 38 | font: 100% Helvetica, sans-serif; 39 | color: #333; 40 | padding: 0.3rem; 41 | } 42 | 43 | .box { 44 | -webkit-transform: rotate(30deg); 45 | -ms-transform: rotate(30deg); 46 | transform: rotate(30deg); 47 | } 48 | 49 | @-webkit-keyframes spinning360 { 50 | 0% { 51 | transform: rotateZ(0deg); 52 | } 53 | 100% { 54 | transform: rotateZ(360deg); 55 | } 56 | } 57 | @-ms-keyframes spinning360 { 58 | 0% { 59 | transform: rotateZ(0deg); 60 | } 61 | 100% { 62 | transform: rotateZ(360deg); 63 | } 64 | } 65 | @keyframes spinning360 { 66 | 0% { 67 | transform: rotateZ(0deg); 68 | } 69 | 100% { 70 | transform: rotateZ(360deg); 71 | } 72 | } 73 | .spinning { 74 | display: inline-block; 75 | height: 1em; 76 | width: 1em; 77 | border-radius: 10%; 78 | border: 1px solid #ccc; 79 | animation: spinning360 3s infinite linear; 80 | } 81 | 82 | /*# sourceMappingURL=output.css.map */ 83 | -------------------------------------------------------------------------------- /examples/sass-demo/output.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["partials/_reset.scss","icons/index.scss","main.scss"],"names":[],"mappings":"AACA;EACE;EACA;EACA;;;ACJF;EACE;EACA;EACA;;;AAGF;EACE;;;ACJF;EACE;;;AAEF;EACE;;AACA;EACE;EACA;EACA;;AAGF;EACE;EACA;;AACA;EACE;;;AAQN;EACE;EACA,OAJc;EAKd;;;AAWF;EALE,mBAKwB;EAJpB,eAIoB;EAHhB,WAGgB;;;AAIxB;EAYA;IACE;;EAEF;IACE;;;AAbF;EASA;IACE;;EAEF;IACE;;;AAVF;EAMA;IACE;;EAEF;IACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA","file":"output.css"} -------------------------------------------------------------------------------- /examples/sass-demo/partials/_reset.scss: -------------------------------------------------------------------------------- 1 | // _reset.scss 2 | * { 3 | box-sizing: border-box; 4 | margin: 0; 5 | padding: 0; 6 | } -------------------------------------------------------------------------------- /examples/static-file-server/.nvmrc: -------------------------------------------------------------------------------- 1 | 9.7.0 2 | -------------------------------------------------------------------------------- /examples/static-file-server/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 王子龙 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/static-file-server/README.md: -------------------------------------------------------------------------------- 1 | # mew 2 | 吸猫社区前端代码 3 | -------------------------------------------------------------------------------- /examples/static-file-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "static-file-server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node ./server/index.js" 9 | }, 10 | "author": "zilong-thu", 11 | "license": "ISC", 12 | "dependencies": { 13 | "koa": "2.4.1", 14 | "koa-static": "^4.0.2", 15 | "lodash": "^4.17.4", 16 | "react": "^16.2.0", 17 | "react-dom": "^16.2.0" 18 | }, 19 | "devDependencies": { 20 | "babel-cli": "^6.26.0", 21 | "babel-preset-env": "^1.6.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/static-file-server/server/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const Koa = require('koa'); 3 | const app = new Koa(); 4 | const serve = require('koa-static'); 5 | 6 | // x-response-time 7 | app.use(async (ctx, next) => { 8 | const start = Date.now(); 9 | await next(); 10 | const ms = Date.now() - start; 11 | ctx.set('X-Response-Time', `${ms}ms`); 12 | }); 13 | 14 | // logger 15 | app.use(async (ctx, next) => { 16 | const start = Date.now(); 17 | await next(); 18 | const ms = Date.now() - start; 19 | console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); 20 | }); 21 | 22 | // static file server 23 | const staticDir = path.join(__dirname, '../static'); 24 | console.log('static file dir: ', staticDir); 25 | app.use(serve(staticDir)); 26 | 27 | 28 | const port = 7001; 29 | app.listen(port); 30 | console.log(`server is running at: \nhttp://localhost:${port}`); 31 | -------------------------------------------------------------------------------- /examples/static-file-server/server/pages/react-ssr/index.js: -------------------------------------------------------------------------------- 1 | // CommonJS 2 | var React = require('react'); 3 | var ReactDOMServer = require('react-dom/server'); 4 | 5 | const html = ReactDOMServer.renderToString(
Hello
); 6 | 7 | console.log(html); 8 | -------------------------------------------------------------------------------- /examples/static-file-server/static/amd-demo/index.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 24px; 3 | text-align: center; 4 | } 5 | 6 | pre { 7 | white-space: pre-wrap; 8 | } -------------------------------------------------------------------------------- /examples/static-file-server/static/amd-demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AMD 模块系统示例 5 | 6 | 7 | 8 | 9 | 10 |

ADM 模块系统示例

11 | 12 |

13 | 
14 |   
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/static-file-server/static/amd-demo/main.js: -------------------------------------------------------------------------------- 1 | requirejs.config({ 2 | paths: { 3 | 'jquery': '/js/jquery-3.2.1' 4 | } 5 | }); 6 | 7 | define([ 8 | '/js/lodash.min.js', 9 | 'jquery', 10 | '/utils/amd-lib-1.js', 11 | ], function(_, $, amdLib_1) { 12 | var str = 'I am using main.js, and I am loaded.'; 13 | 14 | if (_ && (typeof _.chunk === 'function')) { 15 | var res = _.chunk(['a', 'b', 'c', 'd'], 2); 16 | str += '\nLodash.js seems fine too. \n_.chunk gives this result: ' + JSON.stringify(res); 17 | } 18 | 19 | console.log(str); 20 | document.getElementById('console').innerHTML = str; 21 | 22 | console.log('typeof $ => ', typeof $); 23 | if (typeof $ === 'function') { 24 | $('[data-role="jquery-container"]').html('jQuery is loaded too.'); 25 | } 26 | 27 | console.log('amd-lib-1 => ', amdLib_1); 28 | console.log('requirejs define => ', define); 29 | console.log(Object.keys(define)); 30 | }); 31 | -------------------------------------------------------------------------------- /examples/static-file-server/static/common.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 14px; 3 | } -------------------------------------------------------------------------------- /examples/static-file-server/static/home/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 14px; 3 | } -------------------------------------------------------------------------------- /examples/static-file-server/static/home/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 首页 5 | 6 | 7 | 8 | 9 | 10 |

Node.js 静态文件服务器

11 |
Hello World.
12 |

示例清单

13 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/static-file-server/static/home/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/static-file-server/static/home/index.js -------------------------------------------------------------------------------- /examples/static-file-server/static/html-import/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | HTML Imports 5 | 6 | 7 | 8 | 9 |

HTML Imports Demo

10 |
11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/static-file-server/static/html-import/other.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 一个子文档 5 | 8 | 9 | 10 |
子文档的内容
11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/static-file-server/static/jquery-amd-clock/clock.js: -------------------------------------------------------------------------------- 1 | define([], function() { 2 | /** 3 | * 如果num小于10,则在其左侧填充0 4 | * @param {Number} num 5 | * @return {String|Number} 6 | */ 7 | function leftPadding(num) { 8 | if (num < 9) { 9 | return '0' + num; 10 | } 11 | return num; 12 | } 13 | 14 | /** 15 | * 解析当前时间 16 | */ 17 | function getTimeStr() { 18 | var time = new Date(); 19 | var hour = leftPadding(time.getHours()); 20 | var minute = leftPadding(time.getMinutes()); 21 | var second = leftPadding(time.getSeconds()); 22 | 23 | var year = time.getFullYear(); 24 | var month = leftPadding(time.getMonth() + 1); 25 | var day = leftPadding(time.getDate()); 26 | var str = `${hour}:${minute}:${second}`; 27 | 28 | var weekZNArray = ['日', '一', '二', '三', '四', '五', '六']; 29 | var weekDesc = '周' + weekZNArray[time.getDay()]; 30 | 31 | return { 32 | weekDesc: weekDesc, 33 | date: `${year}-${month}-${day}`, 34 | time: str, 35 | }; 36 | } 37 | 38 | /** 39 | * 最终被输出的构造函数 40 | * @param {Object} [props] 41 | * { 42 | * container: DOMElement, 43 | * } 44 | */ 45 | function Clock(props) { 46 | if (!props || !props.container) { 47 | throw new Error('请指定时钟的容器元素'); 48 | return; 49 | } 50 | var container = props.container; 51 | 52 | var $div = document.createElement('div'); 53 | 54 | function display() { 55 | var now = getTimeStr(); 56 | 57 | $div.innerHTML = ` 58 |
59 |
${now.time}
60 |
${now.date + ' ' + now.weekDesc}
61 |
62 | `; 63 | } 64 | 65 | display(); 66 | container.appendChild($div); 67 | 68 | setInterval(function() { 69 | display(); 70 | }, 500); 71 | console.log('时钟已创建'); 72 | } 73 | 74 | return Clock; 75 | }); 76 | -------------------------------------------------------------------------------- /examples/static-file-server/static/jquery-amd-clock/index.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 24px; 3 | text-align: center; 4 | } 5 | 6 | .my-clock { 7 | display: inline-block; 8 | border: 1px solid #ccc; 9 | border-radius: 5px; 10 | padding: 10px; 11 | margin: 10px; 12 | font-size: 24px; 13 | font-weight: bold; 14 | font-family: monospace; 15 | } -------------------------------------------------------------------------------- /examples/static-file-server/static/jquery-amd-clock/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery+AMD组件化时钟示例 5 | 6 | 7 | 8 | 9 | 10 |

jQuery+AMD组件化时钟示例

11 | 12 |
13 | 14 | 15 | 22 | 23 | -------------------------------------------------------------------------------- /examples/static-file-server/static/jquery-amd-clock/index.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | '/jquery-amd-clock/clock.js', 4 | ], function($, Clock) { 5 | var cl = new Clock({ 6 | container: $('#clock-container')[0], 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /examples/static-file-server/static/react/hello-world.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World 6 | 7 | 8 | 9 | 10 | 11 |
12 | 20 | 32 | 33 | -------------------------------------------------------------------------------- /examples/static-file-server/static/utils/amd-lib-1.js: -------------------------------------------------------------------------------- 1 | define(function() { 2 | return { 3 | id: 1, 4 | name: 'An AMD Module', 5 | }; 6 | }); -------------------------------------------------------------------------------- /examples/static-file-server/static/utils/time.js: -------------------------------------------------------------------------------- 1 | ;(function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 3 | typeof define === 'function' && define.amd ? define(factory) : 4 | global.Time = factory(); 5 | }(this, function () { 6 | 'use strict'; 7 | 8 | function Time() { 9 | var param = arguments.length ? new Date(arguments[0]) : new Date(); 10 | this._date = param; 11 | } 12 | 13 | var DAY = 24 * 60 * 60 * 1000; 14 | 15 | Time.prototype.toString = function() { 16 | return this._date.toString(); 17 | }; 18 | 19 | Time.prototype.valueOf = function() { 20 | return this._date.valueOf(); 21 | }; 22 | 23 | return Time; 24 | })); 25 | 26 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/clock/index.css: -------------------------------------------------------------------------------- 1 | /** 2 | * 9 个职业图标 3 | */ 4 | .role-icon { 5 | background-position: 0 0; 6 | background-repeat: no-repeat; 7 | background-size: contain; 8 | height:42px; 9 | width:42px; 10 | margin:0 auto; 11 | border: 1px solid #ccc; 12 | } 13 | 14 | .icon-dot-more { 15 | background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSIwIDAgMjAgNSIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDx0aXRsZT7mm7TlpJo8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iQDF457Sg5p2QIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0i5pu05aSaIiBmaWxsPSIjM0UzRTNFIj4KICAgICAgICAgICAgPHBhdGggZD0iTTE3LjUsNCBDMTYuNjczLDQgMTYsMy4zMjcgMTYsMi41IEMxNiwxLjY3MyAxNi42NzMsMSAxNy41LDEgQzE4LjMyNywxIDE5LDEuNjczIDE5LDIuNSBDMTksMy4zMjcgMTguMzI3LDQgMTcuNSw0IE0xNy41LDAgQzE2LjExOSwwIDE1LDEuMTE5IDE1LDIuNSBDMTUsMy44ODEgMTYuMTE5LDUgMTcuNSw1IEMxOC44ODEsNSAyMCwzLjg4MSAyMCwyLjUgQzIwLDEuMTE5IDE4Ljg4MSwwIDE3LjUsMCBNMi41LDQgQzEuNjczLDQgMSwzLjMyNyAxLDIuNSBDMSwxLjY3MyAxLjY3MywxIDIuNSwxIEMzLjMyNywxIDQsMS42NzMgNCwyLjUgQzQsMy4zMjcgMy4zMjcsNCAyLjUsNCBNMi41LDAgQzEuMTE5LDAgMCwxLjExOSAwLDIuNSBDMCwzLjg4MSAxLjExOSw1IDIuNSw1IEMzLjg4MSw1IDUsMy44ODEgNSwyLjUgQzUsMS4xMTkgMy44ODEsMCAyLjUsMCBNMTAsNCBDOS4xNzMsNCA4LjUsMy4zMjcgOC41LDIuNSBDOC41LDEuNjczIDkuMTczLDEgMTAsMSBDMTAuODI3LDEgMTEuNSwxLjY3MyAxMS41LDIuNSBDMTEuNSwzLjMyNyAxMC44MjcsNCAxMCw0IE0xMCwwIEM4LjYxOSwwIDcuNSwxLjExOSA3LjUsMi41IEM3LjUsMy44ODEgOC42MTksNSAxMCw1IEMxMS4zODEsNSAxMi41LDMuODgxIDEyLjUsMi41IEMxMi41LDEuMTE5IDExLjM4MSwwIDEwLDAiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==); 16 | } 17 | /** endof 9个职业图标 */ -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/clock/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 纯展示组件:一个时钟挂件 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 |
第二个时钟
25 | 26 | 27 | 28 | 29 | 30 | 36 | 37 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/clock/my-clock.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 时钟组件示例 3 | * 使用了 customElements 规范的组件 4 | */ 5 | (function() { 6 | /** 7 | * 如果num小于10,则在其左侧填充0 8 | * @param {Number} num 9 | * @return {String|Number} 10 | */ 11 | function leftPadding(num) { 12 | if (num < 9) { 13 | return '0' + num; 14 | } 15 | return num; 16 | } 17 | 18 | /** 19 | * 解析当前时间 20 | */ 21 | function getTimeStr() { 22 | var time = new Date(); 23 | var hour = leftPadding(time.getHours()); 24 | var minute = leftPadding(time.getMinutes()); 25 | var second = leftPadding(time.getSeconds()); 26 | 27 | var year = time.getFullYear(); 28 | var month = leftPadding(time.getMonth() + 1); 29 | var day = leftPadding(time.getDate()); 30 | var str = `${hour}:${minute}:${second}`; 31 | 32 | var weekZNArray = ['日', '一', '二', '三', '四', '五', '六']; 33 | var weekDesc = '周' + weekZNArray[time.getDay()]; 34 | 35 | return { 36 | weekDesc: weekDesc, 37 | date: `${year}-${month}-${day}`, 38 | time: str, 39 | }; 40 | } 41 | 42 | /** 43 | * 用于创建自定义元素的构造函数 44 | */ 45 | class MyClock extends HTMLElement { 46 | constructor() { 47 | super(); 48 | var shadow = this.attachShadow({mode: 'open'}); 49 | 50 | var $div = document.createElement('div'); 51 | 52 | var display = () => { 53 | var now = getTimeStr(); 54 | this.value = now; 55 | 56 | $div.innerHTML = ` 57 |
${now.time}
58 |
${now.date + ' ' + now.weekDesc}
59 | `; 60 | } 61 | 62 | display(); 63 | shadow.appendChild($div); 64 | 65 | setInterval(function() { 66 | display(); 67 | }, 500); 68 | } 69 | 70 | getValue() { 71 | return this.value; 72 | } 73 | } 74 | 75 | customElements.define('my-clock', MyClock, {extends: 'div'}); 76 | })(); 77 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/shadow-dom/index.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | font-size: 14px; 3 | color: #333; 4 | } 5 | 6 | input { 7 | margin: 20px; 8 | border: 1px solid #999; 9 | border-radius: 5px; 10 | padding: 5px; 11 | } 12 | 13 | table { 14 | border: none; 15 | } 16 | 17 | td { 18 | border-collapse: collapse; 19 | border: 1px solid #ccc; 20 | } -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/shadow-dom/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Shadow DOM 5 | 6 | 7 | 8 | 9 | 10 |

11 | 12 | 22 | 23 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/shadow-dom/slot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 20 | 21 | 34 | 35 | 43 | 44 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/shadow-dom/template-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 |
加载中……
12 | 13 | 22 | 23 | 36 | 37 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/shadow-dom/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
ID名称
18 | 19 | 25 | 26 | 54 | 55 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/word-count/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/word-count/main.js: -------------------------------------------------------------------------------- 1 | class WordCount extends HTMLElement { 2 | constructor() { 3 | super(); 4 | 5 | var wcParent = this.parentNode; 6 | 7 | function countWords(node) { 8 | var text = node.innerText || node.textContent; 9 | var count = text.split(/\s+/g).length; 10 | var countDesc = 'Words: ' + countWords(node); 11 | 12 | return countDesc; 13 | } 14 | 15 | var shadow = this.attachShadow({mode: 'open'}); 16 | 17 | var i = 0; 18 | var text = document.createElement('span'); 19 | text.textContent = i; // countWords(wcParent); 20 | 21 | shadow.appendChild(text); 22 | 23 | setInterval(function() { 24 | text.textContent = i++; 25 | }, 1000); 26 | } 27 | } 28 | 29 | 30 | customElements.define('word-count', WordCount, {extends: 'p'}); 31 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/x-image/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/static-file-server/static/web-component/x-image/x-image.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 27 | 28 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /examples/uglify-js-demo/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uglify-js-demo", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "acorn": { 8 | "version": "5.7.4", 9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", 10 | "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==" 11 | }, 12 | "commander": { 13 | "version": "2.15.1", 14 | "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.15.1.tgz", 15 | "integrity": "sha1-30boZ9D8Kuxmo0ZitAapzK//Ww8=" 16 | }, 17 | "source-map": { 18 | "version": "0.6.1", 19 | "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", 20 | "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" 21 | }, 22 | "uglify-js": { 23 | "version": "3.4.0", 24 | "resolved": "http://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.0.tgz", 25 | "integrity": "sha1-eWdiKCtbXw6v59XIxwjR171boR0=", 26 | "requires": { 27 | "commander": "2.15.1", 28 | "source-map": "0.6.1" 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/uglify-js-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uglify-js-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "use-uglify.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "acorn": "^5.7.4", 13 | "uglify-js": "^3.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/uglify-js-demo/use-acorn.js: -------------------------------------------------------------------------------- 1 | const acorn = require('acorn'); 2 | const fs = require('fs'); 3 | 4 | const code = ` 5 | var a = 1; 6 | function sum(x, y){ return x + y; } 7 | `; 8 | const res = acorn.parse(code); 9 | 10 | fs.writeFileSync('./build/acorn-out.json', JSON.stringify(res)); 11 | -------------------------------------------------------------------------------- /examples/uglify-js-demo/use-uglify.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var UglifyJS = require('uglify-js'); 3 | 4 | // it takes the source code to parse as first argument: 5 | var ast = UglifyJS.parse("function sum(x, y){ return x + y; }"); 6 | 7 | fs.writeFileSync('./build/out.js', JSON.stringify(ast)); 8 | -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-v2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-v2.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-v20.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-v20.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-v3.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-v3.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-v4.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-v4.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版-再也不改了.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版-再也不改了.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版-我发誓这个才是最终版.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版-我发誓这个才是最终版.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版-还是改了一下.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版-还是改了一下.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版-这个是最终版.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版-这个是最终版.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文-最终版.txt -------------------------------------------------------------------------------- /examples/vcs-history/千辛万苦毕业论文/毕业论文.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vcs-history/千辛万苦毕业论文/毕业论文.txt -------------------------------------------------------------------------------- /examples/vue-demo/my-project/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /*.js 5 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = {} -------------------------------------------------------------------------------- /examples/vue-demo/my-project/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Editor directories and files 9 | .idea 10 | .vscode 11 | *.suo 12 | *.ntvs* 13 | *.njsproj 14 | *.sln 15 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/README.md: -------------------------------------------------------------------------------- 1 | # vue-build-using-vue-cli 2 | 3 | > A Vue.js project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | ``` 20 | 21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 22 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | // Use Eslint Loader? 24 | // If true, your code will be linted during bundling and 25 | // linting errors and warnings will be shown in the console. 26 | useEslint: true, 27 | // If true, eslint errors and warnings will also be shown in the error overlay 28 | // in the browser. 29 | showEslintErrorsInOverlay: false, 30 | 31 | /** 32 | * Source Maps 33 | */ 34 | 35 | // https://webpack.js.org/configuration/devtool/#development 36 | devtool: 'cheap-module-eval-source-map', 37 | 38 | // If you have problems debugging vue-files in devtools, 39 | // set this to false - it *may* help 40 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 41 | cacheBusting: true, 42 | 43 | cssSourceMap: true 44 | }, 45 | 46 | build: { 47 | // Template for index.html 48 | index: path.resolve(__dirname, '../dist/index.html'), 49 | 50 | // Paths 51 | assetsRoot: path.resolve(__dirname, '../dist'), 52 | assetsSubDirectory: 'static', 53 | assetsPublicPath: '/', 54 | 55 | /** 56 | * Source Maps 57 | */ 58 | 59 | productionSourceMap: true, 60 | // https://webpack.js.org/configuration/devtool/#production 61 | devtool: '#source-map', 62 | 63 | // Gzip off by default as many popular static hosts such as 64 | // Surge or Netlify already gzip all static assets for you. 65 | // Before setting to `true`, make sure to: 66 | // npm install --save-dev compression-webpack-plugin 67 | productionGzip: false, 68 | productionGzipExtensions: ['js', 'css'], 69 | 70 | // Run the build command with an extra argument to 71 | // View the bundle analyzer report after build finishes: 72 | // `npm run build --report` 73 | // Set to `true` or `false` to always turn it on or off 74 | bundleAnalyzerReport: process.env.npm_config_report 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vue-build-using-vue-cli 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-build-using-vue-cli", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "zilong-thu <809052335@qq.com>", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "lint": "eslint --ext .js,.vue src", 11 | "build": "node build/build.js" 12 | }, 13 | "dependencies": { 14 | "vue": "^2.5.2" 15 | }, 16 | "devDependencies": { 17 | "autoprefixer": "^7.1.2", 18 | "babel-core": "^6.22.1", 19 | "babel-eslint": "^8.2.1", 20 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 21 | "babel-loader": "^7.1.1", 22 | "babel-plugin-syntax-jsx": "^6.18.0", 23 | "babel-plugin-transform-runtime": "^6.22.0", 24 | "babel-plugin-transform-vue-jsx": "^3.5.0", 25 | "babel-preset-env": "^1.3.2", 26 | "babel-preset-stage-2": "^6.22.0", 27 | "chalk": "^2.0.1", 28 | "copy-webpack-plugin": "^4.0.1", 29 | "css-loader": "^0.28.0", 30 | "eslint": "^4.15.0", 31 | "eslint-config-airbnb-base": "^11.3.0", 32 | "eslint-friendly-formatter": "^3.0.0", 33 | "eslint-import-resolver-webpack": "^0.8.3", 34 | "eslint-loader": "^1.7.1", 35 | "eslint-plugin-import": "^2.7.0", 36 | "eslint-plugin-vue": "^4.0.0", 37 | "extract-text-webpack-plugin": "^3.0.0", 38 | "file-loader": "^1.1.4", 39 | "friendly-errors-webpack-plugin": "^1.6.1", 40 | "html-webpack-plugin": "^2.30.1", 41 | "node-notifier": "^5.1.2", 42 | "optimize-css-assets-webpack-plugin": "^3.2.0", 43 | "ora": "^1.2.0", 44 | "portfinder": "^1.0.13", 45 | "postcss-import": "^11.0.0", 46 | "postcss-loader": "^2.0.8", 47 | "postcss-url": "^7.2.1", 48 | "rimraf": "^2.6.0", 49 | "semver": "^5.3.0", 50 | "shelljs": "^0.7.6", 51 | "uglifyjs-webpack-plugin": "^1.1.1", 52 | "url-loader": "^0.5.8", 53 | "vue-loader": "^13.3.0", 54 | "vue-style-loader": "^3.0.1", 55 | "vue-template-compiler": "^2.5.2", 56 | "webpack": "^3.6.0", 57 | "webpack-bundle-analyzer": "^2.9.0", 58 | "webpack-dev-server": "^2.9.1", 59 | "webpack-merge": "^4.1.0" 60 | }, 61 | "engines": { 62 | "node": ">= 6.0.0", 63 | "npm": ">= 3.0.0" 64 | }, 65 | "browserslist": [ 66 | "> 1%", 67 | "last 2 versions", 68 | "not ie <= 8" 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 18 | 19 | 29 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vue-demo/my-project/src/assets/logo.png -------------------------------------------------------------------------------- /examples/vue-demo/my-project/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 85 | 86 | 96 | 97 | 98 | 114 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | 6 | Vue.config.productionTip = false 7 | 8 | /* eslint-disable no-new */ 9 | new Vue({ 10 | el: '#app', 11 | components: { App }, 12 | template: '' 13 | }) 14 | -------------------------------------------------------------------------------- /examples/vue-demo/my-project/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vue-demo/my-project/static/.gitkeep -------------------------------------------------------------------------------- /examples/vue-demo/tax-calc/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-size: 14px; 7 | line-height: 1.8; 8 | font-family: sans-serif; 9 | } 10 | 11 | input { 12 | display: inline-block; 13 | width: 100px; 14 | padding: 3px 0; 15 | border: none; 16 | border-bottom: 1px solid #ccc; 17 | font-size: 14px; 18 | } 19 | 20 | input:focus { 21 | outline: none; 22 | border-color: #aaa; 23 | } 24 | 25 | label { 26 | display: inline-block; 27 | width: 40%; 28 | margin-right: 10px; 29 | text-align: right; 30 | } 31 | 32 | h3 { 33 | text-align: center; 34 | } 35 | 36 | select { 37 | display: inline-block; 38 | height: 30px; 39 | line-height: 30px; 40 | border: 1px solid #eee; 41 | } 42 | 43 | select:focus { 44 | outline: none; 45 | } 46 | -------------------------------------------------------------------------------- /examples/vue-demo/tax-calc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 个税计算器示例 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

个税计算器示例

13 |
14 |
15 |
{{ result.profit }}
16 |
{{ result.real_income }}
17 |
{{ result.tax }}
18 |
19 | 20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/vue-demo/tax-calc/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 中国个税计算算法 3 | * 算法参考:http://www.gerensuodeshui.cn/ 4 | */ 5 | 6 | function taxCalculator(options = { 7 | base: 3500, 8 | income: 10000, 9 | profit: 0, 10 | }) { 11 | const base = options.base || 3500; 12 | 13 | // 税前收入 14 | const income = Number(options.income) || 0; 15 | 16 | // 五险一金缴纳额 17 | const profit = options.profit || Math.round(income * 0.202); 18 | 19 | const income_after_profit = Math.round(income - profit); 20 | 21 | // 应纳税所得额 22 | let income_for_tax = income_after_profit - base; 23 | if (income_for_tax < 0) { 24 | income_for_tax = 0; 25 | } 26 | 27 | // 应纳税所得额(不含税)表 28 | const list = [0, 1455, 4155, 7755, 27255, 41255, 57505, 1000000000000]; 29 | // 税率表 30 | const rate = [0, 0.03, 0.1, 0.20, 0.25, 0.3, 0.35, 0.45]; 31 | // 速算扣除数表 32 | const minus = [0, 0, 105, 555, 1005, 2775, 5505, 13505]; 33 | 34 | let index = list.findIndex((item, i) => { 35 | return (item > income_for_tax) && (list[i - 1] < income_for_tax); 36 | }); 37 | 38 | let tax = 0; 39 | if (income_for_tax) { 40 | tax = Number(income_for_tax * rate[index] - minus[index]).toFixed(2); 41 | } 42 | 43 | // 税后收入 44 | let real_income = (income_after_profit - Number(tax)).toFixed(2); 45 | 46 | return {income, profit, real_income, tax}; 47 | } 48 | 49 | 50 | /** 51 | * 定义一个用于设置个税起征点的组件 52 | */ 53 | Vue.component('user-settings', { 54 | template: ` 55 |
56 | 57 | 60 |
`, 61 | data: function () { 62 | return { 63 | base: 3500, 64 | list: [3500, 4000, 5000, 7000, 10000], 65 | } 66 | }, 67 | methods: { 68 | onSelectChange: function(event) { 69 | var target = event.target; 70 | var value = Number(target.value); 71 | this.$emit('settings', { 72 | base: value, 73 | }); 74 | } 75 | } 76 | }); 77 | 78 | 79 | // Vue app 80 | const app = new Vue({ 81 | el: '#app', 82 | data: { 83 | income: 0, 84 | base: 3500, 85 | }, 86 | computed: { 87 | result: function() { 88 | return taxCalculator({income: this.income, base: this.base}); 89 | } 90 | }, 91 | methods: { 92 | onSettingsChange: function(settings) { 93 | this.base = settings.base; 94 | } 95 | } 96 | }); 97 | 98 | -------------------------------------------------------------------------------- /examples/vue-demo/tax-calc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/vue-demo/tax-calc/screenshot.png -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/.cache/explore.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from '/Users/wzl/gitee/my-book-react-and-engineering/examples/vue-demo/vue-build/src/pages/explore/index.vue'; 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | el: '#app', 8 | render: h => h(App), 9 | }); 10 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/.cache/home.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from '/Users/wzl/gitee/my-book-react-and-engineering/examples/vue-demo/vue-build/src/pages/home/index.vue'; 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | el: '#app', 8 | render: h => h(App), 9 | }); 10 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/.cache/user.followers.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from '/Users/wzl/gitee/my-book-react-and-engineering/examples/vue-demo/vue-build/src/pages/user/followers/index.vue'; 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | el: '#app', 8 | render: h => h(App), 9 | }); 10 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:vue/essential" 9 | ], 10 | "parserOptions": { 11 | "ecmaFeatures": { 12 | "jsx": true 13 | }, 14 | "ecmaVersion": 2018, 15 | "sourceType": "module" 16 | }, 17 | "plugins": [ 18 | "react", 19 | "vue", 20 | ], 21 | "rules": { 22 | "indent": ["error", 2], 23 | "linebreak-style": ["error", "unix"], 24 | "semi": ["warn", "always"] 25 | } 26 | }; -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-build", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "dev": "webpack --watch", 9 | "lint": "eslint -c .eslintrc.js --ext .vue,.js src/" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", 15 | "vue": "^2.5.16" 16 | }, 17 | "devDependencies": { 18 | "babel": "^6.23.0", 19 | "babel-core": "^6.26.3", 20 | "babel-loader": "^7.1.5", 21 | "css-loader": "^1.0.0", 22 | "eslint": "^5.9.0", 23 | "eslint-plugin-react": "^7.11.1", 24 | "eslint-plugin-vue": "^5.0.0-beta.3", 25 | "extract-text-webpack-plugin": "^3.0.2", 26 | "glob": "^7.1.3", 27 | "html-webpack-plugin": "^3.2.0", 28 | "mkdirp": "^0.5.1", 29 | "rimraf": "^2.6.2", 30 | "style-loader": "^0.23.1", 31 | "vue-loader": "^15.4.2", 32 | "vue-style-loader": "^4.1.2", 33 | "vue-template-compiler": "^2.5.16", 34 | "webpack": "^4.15.1", 35 | "webpack-cli": "^3.0.8" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/readme.md: -------------------------------------------------------------------------------- 1 | # Vue 自定义构建示例 -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/src/pages/explore/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | 18 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/src/pages/home/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | 22 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/src/pages/user/followers/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 22 | 23 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/src/vue-template.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from '${path}'; 3 | 4 | Vue.config.productionTip = false; 5 | 6 | new Vue({ 7 | el: '#app', 8 | render: h => h(App), 9 | }); 10 | -------------------------------------------------------------------------------- /examples/vue-demo/vue-build/webpack.config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const glob = require('glob'); 4 | const VueLoaderPlugin = require('vue-loader/lib/plugin'); 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | const webpack = require('webpack'); 7 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 8 | // rimraf 提供了类似 Linux 系统下的 rm 命令 9 | const rimraf = require('rimraf'); 10 | // mkdirp 用于创建文件目录 11 | const mkdirp = require('mkdirp'); 12 | 13 | /** 14 | * 第一步 15 | * 按照约定的格式,寻找页面入口文件 16 | */ 17 | const entryFiles = glob.sync('./src/pages/**/*/index.vue'); 18 | console.log('entryFiles: ', entryFiles); 19 | const entry = {}; 20 | const entryHtmlPlugins = []; 21 | entryFiles.forEach(item => { 22 | let key = item.replace('./src/pages/', '').replace('/index.vue', '').replace('/', '.'); 23 | entry[key] = path.resolve(item); 24 | }); 25 | 26 | /** 27 | * 第二步 28 | * 根据 vue 模板,生成可以被 webpack 使用的入口 js 文件 29 | */ 30 | const pageEntryNames = Object.keys(entry); 31 | let vueTemplateFile = fs.readFileSync('./src/vue-template.js').toString(); 32 | 33 | const CACHE_DIR_NAME = '.cache'; 34 | try { 35 | if (fs.statSync(CACHE_DIR_NAME)) { 36 | rimraf.sync(CACHE_DIR_NAME); 37 | console.log('临时目录已删除'); 38 | } 39 | if (fs.statSync(config.output.path)) { 40 | rimraf.sync(config.output.path); 41 | console.log('构建结果目录已删除'); 42 | } 43 | } catch(e) {} 44 | mkdirp(CACHE_DIR_NAME); 45 | 46 | // html 模板文件路径 47 | const htmlTemplate = path.resolve('./src/index.html'); 48 | 49 | pageEntryNames.forEach(name => { 50 | let content = vueTemplateFile.replace('${path}', path.resolve(entry[name])); 51 | let newEntry = path.resolve(CACHE_DIR_NAME, './', name + '.js'); 52 | fs.writeFileSync(newEntry, content); 53 | const pluginItem = new HtmlWebpackPlugin({ 54 | // 输出时,要写入的文件名 55 | filename: `${name}.html`, 56 | // 读取的模板文件 57 | template: htmlTemplate, 58 | inject: true, 59 | chunks: [name], 60 | }); 61 | 62 | entry[name] = newEntry; 63 | entryHtmlPlugins.push(pluginItem); 64 | }); 65 | 66 | /** 67 | * 第三步 68 | * 声明配置对象,设置 output、文件加载器、插件等 69 | */ 70 | const config = { 71 | mode: 'development', 72 | entry: entry, 73 | output: { 74 | path: path.resolve(__dirname, 'build'), 75 | filename: '[name].[chunkhash].js', 76 | }, 77 | module: { 78 | rules: [ 79 | { 80 | test: /\.vue$/, 81 | loader: 'vue-loader', 82 | }, { 83 | test: /\.js$/, 84 | loader: 'babel-loader', 85 | }, { 86 | test: /\.css$/, 87 | use: ['vue-style-loader', 'css-loader'], 88 | } 89 | ] 90 | }, 91 | plugins: [ 92 | new VueLoaderPlugin(), 93 | ].concat(entryHtmlPlugins), 94 | } 95 | 96 | module.exports = config; 97 | -------------------------------------------------------------------------------- /examples/webpack-mpa/.nvmrc: -------------------------------------------------------------------------------- 1 | 8.4.0 2 | -------------------------------------------------------------------------------- /examples/webpack-mpa/README.md: -------------------------------------------------------------------------------- 1 | # MPA Demo 2 | 3 | 多页面应用示例 4 | 5 | ## 依赖的主要软件的版本 6 | 7 | + Node.js 8.0+ 8 | + npm 3.0+ 9 | + webpack 3.* 10 | + React.js 11 | -------------------------------------------------------------------------------- /examples/webpack-mpa/client/components/layout/base-page.jsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | export default class BasePage extends Component { 5 | renderMain() { 6 | return

I'm a base page!

; 7 | } 8 | 9 | render() { 10 | return ( 11 | {this.renderMain()} 12 | ); 13 | } 14 | } 15 | 16 | 17 | export function initPage(PageContent) { 18 | window.onload = function() { 19 | const container = document.getElementById('react-app'); 20 | ReactDOM.render(, container); 21 | } 22 | } -------------------------------------------------------------------------------- /examples/webpack-mpa/client/components/layout/page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import BasePage from './base-page'; 4 | 5 | export default class Page extends BasePage { 6 | static page(PageConent) { 7 | window.onload = function () { 8 | const container = document.getElementById('react-app'); 9 | ReactDOM.render(, container); 10 | }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/webpack-mpa/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | -------------------------------------------------------------------------------- /examples/webpack-mpa/client/pages/explore/index.jsx: -------------------------------------------------------------------------------- 1 | export default class ExplorePage { 2 | render() { 3 | return ` 4 |
5 | Explore More Here. 6 |
7 | `; 8 | } 9 | } -------------------------------------------------------------------------------- /examples/webpack-mpa/client/pages/explore/style.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/webpack-mpa/client/pages/explore/style.less -------------------------------------------------------------------------------- /examples/webpack-mpa/client/pages/home/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Page, {page} from '$root/client/components/layout/page.jsx'; 3 | 4 | 5 | export default class HomePage extends Page { 6 | componentDidMount() { 7 | console.log('hahahah'); 8 | } 9 | 10 | renderMain() { 11 | return ( 12 |
13 | Hello World. 14 |
15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/webpack-mpa/client/pages/home/style.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/webpack-mpa/client/pages/home/style.less -------------------------------------------------------------------------------- /examples/webpack-mpa/client/pages/user/index.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/examples/webpack-mpa/client/pages/user/index.jsx -------------------------------------------------------------------------------- /examples/webpack-mpa/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "verbose": true 3 | } -------------------------------------------------------------------------------- /examples/webpack-mpa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-multi-page", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "start": "nodemon --watch server ./server/index.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "babel": "^6.23.0", 14 | "babel-loader": "^7.1.1", 15 | "glob": "^7.1.2", 16 | "koa": "^2.3.0", 17 | "lodash": "^4.17.4", 18 | "nodemon": "^1.11.0", 19 | "nunjucks": "^3.0.1", 20 | "pify": "^3.0.0", 21 | "react": "^15.6.1", 22 | "react-dom": "^15.6.1", 23 | "webpack": "3.0.0" 24 | }, 25 | "devDependencies": { 26 | "babel-core": "^6.25.0", 27 | "babel-loader": "^7.1.1", 28 | "babel-preset-env": "^1.6.0", 29 | "html-webpack-plugin": "^2.29.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/webpack-mpa/server/index.js: -------------------------------------------------------------------------------- 1 | const Koa = require('koa'); 2 | const app = new Koa(); 3 | const render = require('./middlewares/render.js'); 4 | 5 | // x-response-time 6 | app.use(async (ctx, next) => { 7 | const start = Date.now(); 8 | await next(); 9 | const ms = Date.now() - start; 10 | ctx.set('X-Response-Time', `${ms}ms`); 11 | }); 12 | 13 | 14 | // logger 15 | app.use(async (ctx, next) => { 16 | const start = Date.now(); 17 | await next(); 18 | const ms = Date.now() - start; 19 | console.log(`${ctx.method} ${ctx.url} ${ms}ms`); 20 | }); 21 | 22 | app.use(render); 23 | 24 | const PORT = 3000; 25 | app.listen(PORT); 26 | console.log('Server running at http://localhost:3000'); 27 | -------------------------------------------------------------------------------- /examples/webpack-mpa/server/middlewares/render.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const nunjucks = require('nunjucks'); 3 | const getWebpackEntryObj = require('../utils/get-entry.js'); 4 | 5 | 6 | function getPageRoutes() { 7 | const reactEntry = getWebpackEntryObj(); 8 | let pageRoutes = {}; 9 | console.log('reactEntry => ', reactEntry); 10 | 11 | Object.keys(reactEntry).forEach(key => { 12 | const _key = /pages(\/.+)\/index/.exec(key)[1]; 13 | pageRoutes[_key] = true; 14 | }); 15 | 16 | pageRoutes['/'] = true; 17 | return pageRoutes; 18 | } 19 | const pageRoutes = getPageRoutes(); 20 | console.log('pageRoutes => ', pageRoutes); 21 | 22 | module.exports = async function (ctx, next) { 23 | console.log('ctx.request.url: ', ctx.request.url); 24 | const tplData = { 25 | content: 'Hello World1', 26 | }; 27 | 28 | if (pageRoutes[ctx.request.url]) { 29 | const compiled = nunjucks.render(path.resolve(__dirname, '../../client/index.html'), tplData); 30 | ctx.body = compiled; 31 | } else { 32 | ctx.body = ''; 33 | } 34 | 35 | await next(); 36 | } 37 | -------------------------------------------------------------------------------- /examples/webpack-mpa/server/utils/get-entry.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const glob = require('glob'); 3 | 4 | 5 | module.exports = function getWebpackEntryObj() { 6 | /** 7 | * files: [ 8 | * './client/pages/home/index.js', 9 | * './client/pages/explore/index.js' 10 | * ] 11 | */ 12 | const files = glob.sync(path.resolve(__dirname, '../../client/pages/**/index.jsx')); 13 | /** 14 | * { 15 | * 'home/index': './client/pages/home/index.js' 16 | * } 17 | */ 18 | const entryObj = {}; 19 | 20 | const reg = /\/client\/(pages\/.+)\.jsx/; 21 | 22 | files.forEach(file => { 23 | let res = reg.exec(file); 24 | if (res && res[1]) { 25 | let key = res[1]; 26 | let val = file; 27 | entryObj[key] = val; 28 | } 29 | }); 30 | 31 | return entryObj; 32 | } 33 | -------------------------------------------------------------------------------- /examples/webpack-mpa/webpack.config.js: -------------------------------------------------------------------------------- 1 | const pify = require('pify'); 2 | const path = require('path'); 3 | const getWebpackEntryObj = require('./server/utils/get-entry.js'); 4 | 5 | 6 | module.exports = { 7 | entry: getWebpackEntryObj(), 8 | output: { 9 | path: path.resolve(__dirname, './build'), 10 | filename: '[name][chunkhash].js', 11 | }, 12 | resolve: { 13 | alias: { 14 | $root: path.resolve(__dirname, '.'), 15 | } 16 | }, 17 | module: { 18 | rules: [ 19 | { 20 | test: /\.jsx?$/, 21 | exclude: /(node_modules|bower_components)/, 22 | use: { 23 | loader: 'babel-loader', 24 | options: { 25 | presets: ['env'] 26 | } 27 | } 28 | } 29 | ] 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Practice-in-Front-End-Engineering-and-Components-Development", 3 | "version": "1.0.0", 4 | "description": "书名:Web前端工程化与组件化开发实践", 5 | "main": "index.js", 6 | "directories": { 7 | "example": "examples" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1", 11 | "s": "gitbook serve ./src", 12 | "c": "find ./src -type f -name \"*.md\" | xargs wc -m | grep total", 13 | "init-hooks": "cp ./scripts/pre-commit.sh ./.git/hooks/pre-commit && chmod a+x ./.git/hooks/pre-commit" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git@git.oschina.net:zilong-thu/my-book-react-and-engineering.git" 18 | }, 19 | "author": "zilong-thu", 20 | "license": "ISC", 21 | "dependencies": { 22 | "gitbook-cli": "^2.3.2", 23 | "gitbook-plugin-custom-js-css": "0.0.1" 24 | }, 25 | "devDependencies": { 26 | "gitbook": "^3.2.3", 27 | "husky": "^0.14.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scripts/pre-commit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | num=$(find ./src -type f -name "*.md" | xargs wc -m | grep total) 3 | echo "" 4 | echo "\033[36m-------------------------\033[0m" 5 | echo "\033[36m 总字数 =$num\033[0m" 6 | echo "\033[36m-------------------------\033[0m" 7 | echo "" 8 | 9 | exit 0 -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | # Web前端工程化与组件化开发实践 2 | 3 | *Practice in Front End Engineering and Components Development* 4 | 5 | [捐助写作](https://borninsummer.com/donate/) 6 | 7 | © 2017-2021 王子龙 8 | -------------------------------------------------------------------------------- /src/book.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Web前端工程化与组件化开发实践", 3 | "styles": { 4 | "website": "styles/common.css", 5 | "pdf": "styles/common.css" 6 | }, 7 | "plugins": [ 8 | "-search", 9 | "-lunr", 10 | "custom-js-css" 11 | ], 12 | "pluginsConfig": { 13 | "custom-js-css": { 14 | "js": [ 15 | "./js/index.js" 16 | ] 17 | } 18 | }, 19 | "pdf": { 20 | "fontSize": 13, 21 | "paperSize": "b5", 22 | "margin": { 23 | "top": 45, 24 | "bottom": 45, 25 | "left": 50, 26 | "right": 50 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 自定义脚本在这里加入到每个页面里 3 | */ 4 | 5 | // GA 统计 6 | (function(win) { 7 | if (win && win.location.hostname === 'localhost') { 8 | return; 9 | } 10 | 11 | (function(i,s,o,g,r,a,m) {i['GoogleAnalyticsObject']=r;i[r]=i[r]||function() {(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); 12 | 13 | ga('create', 'UA-45360338-1', 'auto'); 14 | ga('send', 'pageview'); 15 | })(window); 16 | -------------------------------------------------------------------------------- /src/part-0/0-cover.md: -------------------------------------------------------------------------------- 1 | ## 著作权声明 2 | 3 | 本书采用[署名-非商业性使用-禁止演绎 4.0 国际](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh)协议进行开源写作。 4 | 5 | 您可以自由地: 6 | 7 | + 共享 — 在任何媒介以任何形式复制、发行本作品。只要你遵守许可协议条款,许可人就无法收回你的这些权利。 8 | 9 | 只要你遵守许可协议条款,许可人就无法收回你的这些权利。 10 | 11 | 惟须遵守下列条件: 12 | 13 | + 署名 — 您必须给出适当的署名,提供指向本许可协议的链接,同时标明是否(对原始作品)作了修改。您可以用任何合理的方式来署名,但是不得以任何方式暗示许可人为您或您的使用背书。 14 | + 非商业性使用 — 您不得将本作品用于商业目的。 15 | + 禁止演绎 — 如果您 再混合、转换、或者基于该作品创作,您不可以分发修改作品。 16 | -------------------------------------------------------------------------------- /src/part-0/1-about-author.md: -------------------------------------------------------------------------------- 1 | ## 作者简介 2 | 3 | 我叫王子龙,是一名前端工程师。2013年开始接触前端开发技术,2015年加入美团·猫眼,至今仍在美团工作。 4 | 5 | 我的博客里有更多详细的内容,欢迎访问:[http://borninsummer.com/about](http://borninsummer.com/about)。 6 | 7 | -------------------------------------------------------------------------------- /src/part-0/2-pre.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | 3 | ## 选题背景 4 | 5 | 目前无论是 to B 产品还是 to C 产品,业务复杂度都在不断提升,前端开发人员要保证页面、组件的良好交互体验,提供更好的性能,同时又要保证自己所写代码的可维护性,这是前端工程化命题的一个背景;另外,近几年前端飞速发展,各种框架层出不穷,它们各有不同,然而也有着诸多相似的设计理念。web 框架设计原理、前端工程化、web 组件化开发,这三个主题是 web 前端开发人员在汹涌澎湃的技术浪潮中应该关注的焦点。 6 | 7 | 目前市面上多为介绍框架开发实践,涉及框架原理的较少,而关注前端工程化、组件化开发的书籍,则更为稀少。国内外都如此。这与相关标准或者社区规范一直欠缺有很大关系。而随着 ES6 模块,以及 Web Components 标准的提出,这些问题也都有了大量的实践,已经可以总结出一些经验与问题,供大家思考。 8 | 9 | 随着国内互联网的飞速发展,前端开发人员的需求量也在不断增长,而国内高校很少会专门开设Web前端开发类课程,大多数同学都是靠自学来获得前端开发相应技能。已经有很多专门讲述开发语言的书籍,详细本书的读者也都有所涉猎。但是在实际的工作中,只掌握编程语言技能,是不足以应对每天的开发工作的。现在的前端技术日趋复杂,这对我们的开发效率、代码质量、可维护性等都提出了更高的要求。本书会从工程实践的角度出发,给你讲解可以应对大型项目开发的技能。 10 | 11 | 本书面向的读者是具备一定经验的初中级Web前端开发人员,最好对 JavaScript、CSS 以及 Node.js 有一定的了解。 12 | 13 | ## 内容简介 14 | 15 | 本书简要介绍了当前主流的 Web 前端框架设计原理,然后基于 React 技术栈并结合若干示例来介绍 Web 组件化开发的相关实践,给读者带来一些直观的认识;最后以 webpack 这样的前端开发打包工具为例来介绍前端工程化所要解决的问题,原理与实践。 16 | 17 | ## 图书特色 18 | 19 | 本书的特色是理论与实践并重。理论方面:深入浅出,对组件化、工程化与主流框架设计的核心概念、原理进行剖析;实践方面:结合作者在工作中遇到的具体案例,讲解组件化开发的思路,具备较好的可操作性。 20 | -------------------------------------------------------------------------------- /src/part-1/chapter-2-http/2-http-servers.md: -------------------------------------------------------------------------------- 1 | # HTTP 服务简介 2 | -------------------------------------------------------------------------------- /src/part-1/chapter-2-http/3-http-proxies.md: -------------------------------------------------------------------------------- 1 | # HTTP 抓包与调试 2 | 3 | 参见 [第12章 开发与调试 - HTTP抓包、代理工具](/part-2/chapter-5-debug/5-http-proxy.html) 一节。 4 | -------------------------------------------------------------------------------- /src/part-1/chapter-2-http/index.md: -------------------------------------------------------------------------------- 1 | # HTTP 与 HTTP 服务简介 2 | -------------------------------------------------------------------------------- /src/part-1/chapter-3-js/01-language-features.md: -------------------------------------------------------------------------------- 1 | ## 语言特点 2 | 3 | JavaScript 是一门多范式语言,开发者可以使用过程式风格、面向对象风格以及函数式风格来组织源代码。这一特点使得 JavaScript 能够被不同背景的开发人员所接受。在语言设计上,JavaScript 可谓集众家之所长: 4 | 5 | 6 | 7 | Douglas Crockford 认为,“JavaScript 是第一个成为主流的 Lambda 语言。相对于 Java 而言,JavaScript 与 Lisp 和 Scheme 有更多的共同点。它是披着 C 外衣的 Lisp”[1]。其在语言设计上的优越性,使得 JavaScript 在今天愈加强大。 8 | 9 | **弱类型** 10 | 11 | JavaScript 是一门弱类型,或者“动态类型”的语言,并不意味着 JavaScript 语言是“没有类型”的,而是指用户声明标识符(变量)时不必指定类型,且标识符指向的值的类型可以随意更改,即变量的类型通常在运行时确定。 12 | 13 | ```javascript 14 | var a = 'some string'; // 初始化时指定 a 为字符串类型 15 | 16 | a = {id: 1}; // 但之后也可以让 a 指向一个对象,成为一个引用类型 17 | ``` 18 | 19 | **面向对象** 20 | 21 | 基于原型,JavaScript 支持面向对象的程序设计模式。 22 | 23 | ```javascript 24 | // 封装 25 | function Person(name = '', age = null) { 26 | this.name = name; 27 | this.age = age; 28 | } 29 | 30 | Person.prototype.sayHello = function() { 31 | var str = `Hi, I am ${this.name}.`; 32 | if (this.age || this.age === 0) { 33 | str += ` I'm ${this.age} years old.`; 34 | } 35 | console.log(str); 36 | } 37 | 38 | var wang = new Person('Wang', 29); 39 | wang.sayHello(); 40 | 41 | // 继承 42 | function Student() { 43 | Person.apply(this, Array.prototype.slice.call(arguments)); 44 | } 45 | Student.prototype = new Person(); 46 | 47 | var st = new Student('XiaoMing'); 48 | st.sayHello(); // 调用父类定义给实例的方法 49 | ``` 50 | 51 | 此外,利用每个函数内部的 `arguments` 上下文变量对实参进行数量与类型的检查,可以实现函数的重载。 52 | 53 | **函数式风格** 54 | 55 | JavaScript 里的函数是“一等公民”,即函数本身亦是对象,一个函数可作为另一个函数的返回值,也可以作为其他函数的传入参数。由于 JavaScript 在设计出来时就借鉴了函数式编程语言 Scheme,因此对函数式风格的编程支持得很好。 56 | 57 | ```javascript 58 | var arr = [1, 2, 3, 4]; 59 | // 内置的函数式编程风格的API 60 | var b = arr.map(item => item * item); 61 | ``` 62 | 63 | 可以用常见的科里化(curring)做到一些很酷的事情: 64 | 65 | ```javascript 66 | function multi(x = 1) { 67 | function m(y = 1) { 68 | x = x * y; 69 | return m; 70 | } 71 | 72 | m.toString = function() { 73 | return '' + x; 74 | }; 75 | 76 | m.valueOf = function() { 77 | return x; 78 | } 79 | 80 | return m; 81 | } 82 | 83 | console.log(multi(2)); // => 1 84 | console.log(multi(2)(4)); // => 8 85 | console.log(multi(1)(2)(3)); // => 6 86 | ``` 87 | 88 | 此外,ECMAScript6 开始列入标准的箭头函数(Arrow-Functions)可以轻松地实现 λ 表达式(Lambda Expressions)风格的代码: 89 | 90 | ```javascript 91 | var y = x => x * x; 92 | var val = y(2); // val 的值为 4 93 | ``` 94 | 95 | ### 参考资料 96 | 97 | 1. Douglas Crockford. JavaScript 语言精粹[M]. 北京: 电子工业出版社, 2012. 98 | -------------------------------------------------------------------------------- /src/part-1/chapter-3-js/02-js-engine.md: -------------------------------------------------------------------------------- 1 | # JavaScript 引擎 2 | 3 | 史上最早的 JavaScript 引擎当属 Brendan Eich 发明 JavaScript 顺便一起开发的 SpiderMonkey 了。 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/part-1/chapter-3-js/03-js-future.md: -------------------------------------------------------------------------------- 1 | # 未来展望 2 | 3 | Lisp 社区的领袖之一 Richard Gabriel 在一篇论文[1]里指出:**在软件设计发展过程的奋斗中,那些促成快速传播(传染)的特征,如实现的简单性和可移植性等,比起设计的正确性和完备性更为有效。**JavaScript 语言的崛起也体现了类似的规律。它一开始的设计并不完美,有太多缺陷,然而却因为及其简单的设计而霸占浏览器世界。 4 | 5 | 在占据了浏览器市场之后,JavaScript 才迎来众多开发者的关注,并且延伸到服务器端、区块链、深度学习等领域中。在过去的几十年里,这门语言广泛参考社区的优秀实践,不断完善自己的标准。 6 | 7 | 与 JavaScript 同时期诞生的 Java 编程语言的设计目标是“一处编写,到处运行”(write once, run anywhere),并且支持网页中嵌入交互程序(applets)。但由于 Java 语言的所有者 Sun 公司的一系列技术和战略失误,Java 没有实现这两个最初的设计目标(Eric S. Raymond,《Unix编程艺术》)。JavaScript 却借着浏览器端的垄断地位不断向其他领域延伸,以至于 Stackoverflow 的创始人之一 Jeff Atwood 做出了这样的预言:“任何可以使用 JavaScript 实现的程序终将会使用 JavaScript 实现”(Any application that can be written in JavaScript, will eventually be written in JavaScript)。 8 | 9 |
10 | 11 |
CoffeeScript is a little language that compiles into JavaScript.
12 |
13 | 14 | 2009 年,Jeremy Ashkenas 发明了 CoffeeScript,一种可以被编译为 ECMAScript 的语言(相当于 ECMAScript 的一种方言)。CoffeeScript 的出现很大程度上是因为 JavaScript 语法上的欠缺。在参考了一些其他语言(例如 Ruby 和 Python)的特性,以及结合社区的喜好,CoffeeScript 给出了一套解决方案,提出了诸如 `let`、`const`、箭头函数(用的是细箭头 `->`)、解构赋值(Destructuring Assignment)、函数默认值等方便好用的语法特性。JavaScript 的发明人 Brendan Eich 在 2011 年 JSConf 上的演讲里特别提到了 CoffeeScript 并且列举了未来的 ECMAScript 会出现的一些特性,其中就有许多特性是 CoffeeScript 社区已经给出的。 15 | 16 | 在 2015 年 7 月正式发布的 ECMAScript 2015 标准(即 ECMAScript 6th Edition)中,CoffeeScript 的诸多特性都被采纳。有些特性即将被下一个 ECMAScript 版本采纳。所以,CoffeeScript 算是完成了自己的“历史使命”,以社区的力量推动了标准化进程。Ruby 语言的发明者松本行弘在《代码的未来》一书里讨论过 JavaScript 及方言 CoffeeScript,他当时认为 CoffeeScript “无论在服务器端还是客户端,今后其应用范围都会越来越广,可以说是将来值得期待的语言之一”。现在来看,标准化才是未来的方向呢。 17 | 18 | ### 语言特性 19 | 20 | **类型的重要程度增加** 21 | 22 | 在复杂的应用中,类型系统有助于提升系统的健壮性,帮助程序员提前发现问题。TypeScript 这样的社区方言,将来可能会有些特性被 ECMAScript 标准所采纳。 23 | 24 | **新的基本类型** 25 | 26 | 以数值为例,ECMAScript 语言中 `Number` 本质上是是完全按照 IEEE Standard for Floating-Point Arithmetic (IEEE 754)[1,2] 实现的。`Number` 类型实际上就是双精度浮点数类型(double precision floating-point format),类似 C 语言里的 `double`。这种数值类型表达整数的能力比较有限。未来可能会增加像 `BigInt` 这样的基本类型: 27 | 28 | ```javascript 29 | var max = Number.MAX_SAFE_INTEGER; 30 | console.log(max); 31 | // 9007199254740991 32 | 33 | var bigA = BigInt(max) + 100n; 34 | console.log(bigA); 35 | // 9007199254741091n 36 | ``` 37 | 38 | 这个基本类型目前处在 Stage3 阶段。此阶段的含义是 Candidate(候选),“Indicate that further refinement will require feedback from implementations and users”,即需要实现者(通常是浏览器厂商)与用户进一步优化与反馈。目前 Chrome67 已经开始支持 BigInt。还需要有至少一个其他浏览器厂商或JS运行时给出具体的实现。 39 | 40 | 41 | ## 参考资料 42 | 43 | 1. 《Lisp: 好消息,坏消息以及如何获得大胜》(Lisp: Good News, Bad News, and How to Win Big) 44 | 2. CoffeeScript 官网, https://coffeescript.org/ 45 | -------------------------------------------------------------------------------- /src/part-1/chapter-3-js/index.md: -------------------------------------------------------------------------------- 1 | # JavaScript 简介 2 | 3 | JavaScript 最初是作为一种脚本语言被发明出来。“脚本语言”似乎表明这是一种玩具语言,并非可登大雅之堂者。然而这么多年下来,很多被称作脚本的编程语言(Perl、Python、JavaScript)都已经超越了最初意义的脚本用途,而是成为威力相当强大的独立通用编程语言。 4 | 5 | 在流传甚广的以打趣为目的的《编程语言野史》一文这样描述 JavaScript 这门语言的诞生: 6 | 7 | > 1995 – Brendan Eich 读完了历史上所有在程序语言设计中曾经出现过的错误,自己又发明了一些更多的错误,然后用它们创造出了LiveScript。之后,为了紧跟Java语言的时髦潮流,它被重新命名为JavaScript。再然后,为了追随一种皮肤病的时髦潮流,这语言又被命名为ECMAScript。 8 | 9 | 不同的 JavaScript 引擎可能采取不同的编译器实现方法。在设计 JavaScript 时,Brendan Eich 受 Java 影响颇大,因此使用了字节码解释器(bytecode interpreter)对 JavaScript 解释执行[1]。而著名的 V8 引擎,在运行前先将 JavaScript 编译为机器码(而非字节码或是解释执行它),以此提升性能[2]。 10 | 11 | JavaScript 发布后,获得了巨大的成功。这个语言的发明与繁荣,印证了 MVP(Minimum Viable Product,最小可用产品)理念的价值。简单、跨平台、分布式使得 JavaScript 很快成为浏览器端的唯一语言,这种重要性反过来迫使各个巨头携手推进其标准化。1997年,由网景、昇阳、微软、宝蓝等公司组织及个人组成的技术委员会在 ECMA(European Computer Manufactures Association,欧洲计算机制造商协会)确定定义了一种名叫 ECMAScript 的新脚本语言标准,规范名为 ECMA-262。 12 | 13 | 14 | 15 | ECMAScript 有过3个重大版本,分别是 1999 年的 ES3、2009 年的 ES5 以及 2015 年的 ES6。从 ES6 开始,TC39 委员会决定每年都发布一次 ECMAScript 的新版本,并以年份作为版本标识。例如 2017 年发布的标准就是 ECMAScript 2017[3]。 16 | 17 | ## 参考资料 18 | 19 | JavaScript 的最佳学习读物主要有 Nicholas C. Zakas 的《JavaScript高级程序设计(第3版)》,David 的《JavaScript权威指南(第6版)》,以及 Douglas Crockford 的《JavaScript语言精粹》。对于 ES6+ 特性的学习,国内有阮一峰的《ES6标准入门》,国外有 Nicholas C. Zakas 的《深入理解 ES6》。此外,《你不知道的 JavaScript》系列读物,也是非常有趣。 20 | 21 | 1. [JavaScript at 20, by Brendan Eich](http://brendaneich.github.io/ModernWeb.tw-2015/#1) 22 | 2. [V8 engine | wikipedia](https://en.wikipedia.org/wiki/V8_engine) 23 | 3. [Standard ECMA-262, ECMAScript® 2017 Language Specification](http://www.ecma-international.org/publications/standards/Ecma-262.htm) 24 | -------------------------------------------------------------------------------- /src/part-1/chapter-4-webfe-apps/index.md: -------------------------------------------------------------------------------- 1 | # 前端可以做哪些应用 2 | 3 | 在应用程序方面,JavaScript 承担了非常的业务场景。 4 | 5 | 前端应用按照运行环境,可以分为服务端、浏览器端、小程序三类。按照是否需要在单一页面内完成所有交互,可以分为单页面应用、多页面应用。 6 | 7 | 下面我们从产品形态的角度介绍前端常见的应用场景。 8 | 9 | ### 展示页面 10 | 11 | 展示类的页面,通常属于多页面应用。无论是以服务端渲染还是浏览器端渲染,页面的交互都比较少,以呈现内容为主。例如新闻类页面、博客、论坛等等。 12 | 13 | ### 表单、中台系统 14 | 15 | JavaScript 诞生初期就为表单校验提供了极大的便利,在今天依然如此。对于以数据的增删改查为主的中台系统,表单是不可或缺的一部分。 16 | 17 | ### 富文本编辑 18 | 19 | 网页富文本编辑是当今 Web 产品中非常重要的功能。富文本编辑器的技术较为复杂。目前有许多优秀的开源编辑器(常见的是 markdown 一类的编辑器),以及免费的文本类产品(例如 Google Docs)。 20 | 21 | ### 音/视频播放 22 | 23 | 在影音多媒体网站中,音/视频播放器是独具挑战的专门领域。 24 | 25 | ### 即时通信工具 26 | 27 | 代表产品:Slack。 28 | 29 | ### 地图工具 30 | 31 | 代表产品:高德地图,百度地图,腾讯地图,搜狗地图。 32 | 33 | ### Web 游戏 34 | 35 | 36 | ### 数据可视化 37 | 38 | 代表类库:ECharts.js,D3.js,highcharts.js。 39 | 40 | ### 区块链技术 41 | 42 | 43 | ### 机器学习 44 | 45 | tensorflow.js 46 | 47 | ------------------- 48 | 49 | **后端服务** 50 | 51 | 借助于 Node.js,相当多的 JavaScript 开发者已经在生产环境下维护着自己的前端服务,这些服务承担着路由控制、页面渲染、请求代理与数据聚合等功能,少数公司可能还使用了 JavaScript 来连接数据库(例如MySQL/MongoDB)并提供微服务。这种从前到后都使用 JavaScript 进行开发的全栈模式,减少了语言间的沟通障碍,有一定的优势,也有一定的潜在风险,例如对开发人员的要求变高可能面临暂时的人才储备不足,JavaScript 的弱类型带来的不稳定性,等等。未来应该会有更多的公司和开发者去尝试全栈 JavaScript 开发模式。 52 | 53 | ------------------- 54 | 55 | -------------------------------------------------------------------------------- /src/part-1/chapter-5-nodejs/01-nodejs.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/chapter-5-nodejs/01-nodejs.md -------------------------------------------------------------------------------- /src/part-1/chapter-5-nodejs/02-npm.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/chapter-5-nodejs/02-npm.md -------------------------------------------------------------------------------- /src/part-1/chapter-5-nodejs/03-yarn.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/chapter-5-nodejs/03-yarn.md -------------------------------------------------------------------------------- /src/part-1/chapter-html/index.md: -------------------------------------------------------------------------------- 1 | # HTML 简介 2 | 3 | HTML(HyperText Markup Language,超文本标记语言)是构成 Web 世界的关键基石,它定义了网页的语义和结构。 4 | 5 | 如本书第一章“Web前端简史”所述,HTML 是由蒂姆·伯纳斯-李及其在创建世界上第一个网站时定义的。 6 | -------------------------------------------------------------------------------- /src/part-1/images/coffeescript-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/coffeescript-logo.png -------------------------------------------------------------------------------- /src/part-1/images/dynamic_page_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/dynamic_page_en.png -------------------------------------------------------------------------------- /src/part-1/images/emacs-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/emacs-logo.png -------------------------------------------------------------------------------- /src/part-1/images/homebrew-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/homebrew-logo.png -------------------------------------------------------------------------------- /src/part-1/images/homebrew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/homebrew.png -------------------------------------------------------------------------------- /src/part-1/images/http-3-types.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/http-3-types.png -------------------------------------------------------------------------------- /src/part-1/images/http-client-and-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/http-client-and-server.png -------------------------------------------------------------------------------- /src/part-1/images/http-requests-trends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/http-requests-trends.png -------------------------------------------------------------------------------- /src/part-1/images/http-version-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/http-version-history.png -------------------------------------------------------------------------------- /src/part-1/images/iterm2-autocomplete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/iterm2-autocomplete.png -------------------------------------------------------------------------------- /src/part-1/images/iterm2-hotkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/iterm2-hotkey.png -------------------------------------------------------------------------------- /src/part-1/images/iterm2-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/iterm2-logo.png -------------------------------------------------------------------------------- /src/part-1/images/iterm2-multi-panes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/iterm2-multi-panes.png -------------------------------------------------------------------------------- /src/part-1/images/javascript-timeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/javascript-timeline.png -------------------------------------------------------------------------------- /src/part-1/images/js-origin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/js-origin.png -------------------------------------------------------------------------------- /src/part-1/images/kernel_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/kernel_layout.png -------------------------------------------------------------------------------- /src/part-1/images/logo2x.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/logo2x.psd -------------------------------------------------------------------------------- /src/part-1/images/mvc-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/mvc-process.png -------------------------------------------------------------------------------- /src/part-1/images/node_modules_vs_black_holes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/node_modules_vs_black_holes.jpg -------------------------------------------------------------------------------- /src/part-1/images/nodejs-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/nodejs-logo.png -------------------------------------------------------------------------------- /src/part-1/images/npm-view-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/npm-view-01.png -------------------------------------------------------------------------------- /src/part-1/images/oh-my-zsh-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/oh-my-zsh-01.png -------------------------------------------------------------------------------- /src/part-1/images/os-windows1.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/os-windows1.0.png -------------------------------------------------------------------------------- /src/part-1/images/sublime-01-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/sublime-01-logo.png -------------------------------------------------------------------------------- /src/part-1/images/three-os-logos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/three-os-logos.png -------------------------------------------------------------------------------- /src/part-1/images/vim-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/vim-logo.png -------------------------------------------------------------------------------- /src/part-1/images/vscode-debug-node-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/vscode-debug-node-1.png -------------------------------------------------------------------------------- /src/part-1/images/vscode-shell-command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/vscode-shell-command.png -------------------------------------------------------------------------------- /src/part-1/images/web-history-1-static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/web-history-1-static.png -------------------------------------------------------------------------------- /src/part-1/images/yarn-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-1/images/yarn-logo.png -------------------------------------------------------------------------------- /src/part-1/index.md: -------------------------------------------------------------------------------- 1 | # 基础篇 2 | 3 | 本章会对前端、JS、HTML、CSS 分别进行发展历史的介绍并对未来进行展望。 4 | 5 | 因为很多我们当前采用的工程化、组件化方案,可能会随着技术的发展而逐渐在语言层面上标准化,那么很有必要关注前端核心技术的未来发展趋势。 6 | 7 | 8 | 9 | Web 组件化开发 10 | 11 | 前端工程化主要关注非运行时的开发问题(文件处理、代码编译等),组件化则关注前端代码在运行时的功能实现方式及功能模块之间的关系。 12 | -------------------------------------------------------------------------------- /src/part-1/welcome-on-board/3-node-and-npm.md: -------------------------------------------------------------------------------- 1 | ## 安装 Node.js 环境 2 | 3 | ### 安装 nvm 4 | 5 | ```bash 6 | # 这个命令的意思是,从该网址下载文本内容,然后将内容交给 bash 去运行 7 | $ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash 8 | ``` 9 | 10 | ### 安装 Node 11 | 12 | ```bash 13 | $ nvm install 12.0.0 14 | ``` 15 | 16 | ### 安装 Yarn 17 | 18 | 19 | ```bash 20 | $ curl --compressed -o- -L https://yarnpkg.com/install.sh | bash 21 | ``` 22 | -------------------------------------------------------------------------------- /src/part-1/welcome-on-board/index.md: -------------------------------------------------------------------------------- 1 | # Welcome on Board 2 | 3 | > 你好, 4 | > 5 | > 欢迎你加入猫眼前端组,感谢你对我们的认可,也向我们证明了你的实力。 6 | > “既往不恋,纵情向前”,是美团的口号,今天送给你,让我们一起扬帆起航。那么接下来开启你在美团的第一天吧! 7 | 8 | 我加入猫眼前端团队的第一天,组长分享了一篇题目为“Welcome on board”的内部 wiki,上面正是开头的一段话。 9 | 10 | 这篇 wiki 给出了入职第一天的员工需要进行的开发环境配置、软件安装等准备工作清单。正所谓“工欲善其事必先利其器”,其中很多工具都可以提升前端工程师的开发效率,所以在这里,我们也从配置你的开发环境开始。 11 | -------------------------------------------------------------------------------- /src/part-1/示例清单.md: -------------------------------------------------------------------------------- 1 | # 示例清单 2 | 3 | + 如果你没有任何框架,用原生 JavaScript 实现一个简单的静态资源服务器 4 | + truck.js 及其应用(如何组织你的 jquery 源码) 5 | + webpack 处理非 react 程序 6 | + React.js 工程化&组件化开发(源码组织) 7 | + vue 8 | + polymer.js -------------------------------------------------------------------------------- /src/part-2/art-about-code.md: -------------------------------------------------------------------------------- 1 | # 关于代码 2 | 3 | 本书源码的运行,用到了 Node.js、Webpack 等软件,版本都尽可能使用最新的。 4 | 5 | + Node.js@8.* 6 | + webpack@3.* 7 | + react@15 8 | -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/03-git-workflow.md: -------------------------------------------------------------------------------- 1 | ## Git 工作流 2 | 3 | ### 多人协同开发 4 | 5 | 在多人协同开发时,Git 工作流程就显得尤为重要。当开启一个新特性的开发时,通常从主干分支(例如 `master`) `checkout` 出一个新分支,作为本次特性开发功能的公共主分支,例如命名为 `feature/user-center`;而参与本次特性开发的人员,可以从 `feature/user-center` 再 `checkout` 属于自己的私有分支,例如 `wzl/feature/user-center`。Git 分支的创建可以说是零成本的,这也是其最强大的特性之一。 6 | 7 | Vincent Driessen 在2010年的一篇文章《A successful Git branching model》[3] 介绍了在这样的场景下,如何使用 Git 进行高效开发。其核心观点之一是围绕着“中心化与去中心化并存”而采取的分支策略: 8 | 9 | 10 | 11 | ### 良好的提交信息 12 | 13 | 在使用 Git 的过程中,可以发现 Git 是会强制每次提交都要写提交消息(commit message)的,这也算是 Linus 的良好编程习惯的体现。准确恰当的提交信息对于回溯项目开发历程、寻找特定功能的代码片段等等,都很有帮助。 14 | 15 | 真正到了要写提交信息的时候,很多人可能会图省事,使用 `...`,或者 `abc` 这养的内容蒙混过去。这可不是什么好习惯。Git 的提交信息应该简明扼要,描述当前提交所做的主要的事情。可以使用一些可以描述所做改动的关键词作为前缀然后书写详细的信息。 16 | 17 | 关键词有两类,一类是动词,表示进行的动作;另一类是名词,可以与业务相关,也可以是动词的名词化形式。下面是一些常见的关键词: 18 | 19 | + `add`,或 `feature`,表示添加新功能 20 | + `fix`,缺陷修复 21 | + `hotfix`,紧急的缺陷修复 22 | + `update`,对已有功能进行更改或优化 23 | + `remove`,或者 `rm`、`delete`,删除部分代码、功能 24 | + `refactor`,重构了一些代码、功能 25 | + `workflow`,工作流程更改 26 | + `chore`,琐碎的修改 27 | 28 | ```bash 29 | # 新增了支持用户上传文件的功能 30 | $ git commit -m 'add: 上传文件功能' 31 | 32 | # 修复了一个线上问题 33 | $ git commit -m 'fix: **页面数字取值问题' 34 | 35 | # 对某些代码进行了重构 36 | $ git commit -m 'refactor: 重构商品列表页' 37 | ``` 38 | 39 | 此外,对于每个项目,可以用业务相关的名词作为关键词前缀。例如: 40 | 41 | ```bash 42 | # docs 表示这是对文档进行的修改 43 | $ git commit -m 'docs: 更新接口文档' 44 | ``` 45 | -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/04-server-side-git.md: -------------------------------------------------------------------------------- 1 | # 服务器端 Git 2 | -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/images/centr-decentr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-0-git-and-vcs/images/centr-decentr.png -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/images/chinese-char-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-0-git-and-vcs/images/chinese-char-2.png -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/images/chinese-char.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-0-git-and-vcs/images/chinese-char.png -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/images/git-3-areas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-0-git-and-vcs/images/git-3-areas.png -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/images/git-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-0-git-and-vcs/images/git-logo.png -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/images/local-vcs-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-0-git-and-vcs/images/local-vcs-demo.png -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/images/local-vcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-0-git-and-vcs/images/local-vcs.png -------------------------------------------------------------------------------- /src/part-2/chapter-0-git-and-vcs/index.md: -------------------------------------------------------------------------------- 1 | # 版本控制 2 | 3 | 版本控制系统(VCS,Version Control System)通常用于管理软件开发过程中的源代码文件,好的版本控制系统应该具备多人并行开发、代码变更记录、文件冲突处理机制、分支策略、易于回归等特性。版本控制系统经历过三代演进: 4 | 5 | ** 本地版本控制(Local Version Control System)** 6 | 7 | 最原始的本地备份式版本控制,也称为“手工版本控制”。这种版本控制策略,本质上只是文件备份,最常用的方式就是将当期文件复制到另一个目录(可能会添加时间戳)。不少人也许有过类似下面这样命名文件的经历,这其实就是一种本地版本控制策略: 8 | 9 | 毕业论文命名 10 | 11 | 后来程序员们设计了简单的本地文件数据库系统,并且为文件的备份、命名、签出等操作提供了自动化的命令,从而形成了本地版本控制系统: 12 | 13 | 14 | 15 | 本地版本控制的代表软件是 RCS(Revision Control System),其诞生于 1982 年,由 Walter F. Tichy 发布,隶属于 GNU 项目。 16 | 17 | ** 集中式版本控制系统(Centralized Version Control System)** 18 | 19 | 然后是以 Subversion(通常被叫做 svn) 为代表的中央版本控制系统。 20 | 21 | ** 分布式版本控制系统(Distributed Version Control System)** 22 | 23 | 再后来,出现了以 Git 为代表的分布式版本控制系统。 24 | 25 | Subversion(2000年)、Git(2005年) 都是免费开源软件,Git 出现的更晚一些,也吸收了前者的很多优点,两者各有优缺点。不过随着 Github 网站的崛起,以及自由软件开发的持续热浪,越来越多的程序员新人更倾向于使用 Git 作为自己主要的版本控制工具,对前端开发人员来说更是如此—— JavaScript 向来是 Github 上面最受欢迎的编程语言(GitHub Universe,2017)。 26 | 27 | ### 参考资料 28 | 29 | 1. [Revision Control System | wikipedia](https://en.wikipedia.org/wiki/Revision_Control_System) 30 | 2. [Using Git Hooks in Your Development Workflow](https://scotch.io/tutorials/using-git-hooks-in-your-development-workflow) 31 | -------------------------------------------------------------------------------- /src/part-2/chapter-1-模块系统/images/hatton-2-repaint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-1-模块系统/images/hatton-2-repaint.png -------------------------------------------------------------------------------- /src/part-2/chapter-1-模块系统/images/hatton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-1-模块系统/images/hatton.png -------------------------------------------------------------------------------- /src/part-2/chapter-1-模块系统/images/js-module-too-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-1-模块系统/images/js-module-too-small.png -------------------------------------------------------------------------------- /src/part-2/chapter-1-模块系统/images/require-js-effect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilong-thu/Practice-in-Front-End-Engineering-and-Components-Development/a3cee69618473444aacf8e87d02ee1bc4303de39/src/part-2/chapter-1-模块系统/images/require-js-effect.png -------------------------------------------------------------------------------- /src/part-2/chapter-1-模块系统/section-1-概述.md: -------------------------------------------------------------------------------- 1 | # 模块系统概述 2 | 3 | JavaScript 模块系统旨在解决大中型前端应用脚本管理与加载问题。 4 | 5 | ## 模块系统的重要性 6 | 7 | ### 减少 bug 率 8 | 9 | Hatton[1] 研究统计了代码行数与出现的 bug 数量的关系,给出了下面的曲线。结论之一是,一个模块的代码逻辑行数在200~400行之间是最佳状态,此时缺陷的密度最低。而且,Hatton 的研究发现,这个行数与所使用的编程语言无关。如果考虑到必要的注释、空行等,一个可读性好、思路清晰、易于维护的模块文件代码总行数通常在400~800行之间。 10 | 11 |
12 | 13 |
Bug 数量、bug 密度随模块大小的变化趋势(根据 Hatton 的曲线重新绘制)。
14 |
15 | 16 | 模块的代码行数太小,也会带来 bug 密度的提升,主要是因为模块与模块之间的 API 成本相应增加导致。例如,在一个模块中,当你需要通过追溯多个模块才能发现某个方法、依赖的来源时,这种成本就可以理解为模块间API的成本。 17 | 18 | 19 | 20 | 过多的跨模块查找,形成了模块间“沟通”成本。这会干扰你的注意力,使得 bug 产生的概率增加。 21 | 22 | ### 代码复用与正交性 23 | 24 | 在程序员的文化里,有一条关于编码行为的 **DRY** 准则常被津津乐道: 25 | 26 | > Don't Repeat Yourself.(不要重复自身) 27 | > 28 | > -- The Pragmatic Programmer. 《程序员修炼之道》 29 | 30 | DRY 大意是不要随意复制已有代码,要考虑能否复用相关代码。这体现了“正交性”的设计思想。 31 | 32 | **正交**是一个非常优雅的术语。在欧几里得空间里,两个向量点积为零则为正交;在物理学中,正交表现为运动的独立性。而在软件工程的领域中, 33 | 模块的正交性有这样的特点:在纯粹的正交性设计中,任何操作均无副作用;每个操作只改变一件事情;要修改任何一个属性,有且仅有一个方法可以使用(E. S. M.,《Unix编程艺术》)。 34 | 35 | 模块化使得同一份代码可以不经复制来做到复用,从而提升系统的正交性。 36 | 37 | ### 有利于单元测试 38 | 39 | 在计算机程序设计中,单元测试(Unit Testing)是非常重要的一个环节,其有助于提升代码质量、确保代码可靠性。单元测试又叫模块测试,通常针对小的代码片段编写测试用例。 40 | 41 | 前端开发中许多功能需要依靠单元测试来确保代码正常运行。例如版本判断与比较、客户端识别模块(解析 `User-Agent`)、URL 处理与解析等等。 42 | 43 | ## 模块化解决方案分类 44 | 45 | 回顾前端模块化进程,下面几种 JavaScript 模块化解决方案先后出现: 46 | 47 | + 刀耕火种时代 48 | + CommonJS 模块规范及在 Node.js 里的实现 49 | + AMD,异步模块定义 50 | + ESM,ECMAScript 模块系统 51 | 52 | ## 参考资料 53 | 54 | 1. IEEE Software. Les Hatton. “Re-examining the Defect-Density versus Component Size Distribution”. March/April 1997. 55 | -------------------------------------------------------------------------------- /src/part-2/chapter-1-模块系统/section-2-刀耕火种时代.md: -------------------------------------------------------------------------------- 1 | # 刀耕火种时代 2 | 3 | HTML ` 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ``` 23 | 24 | ## 参考资料 25 | 26 | 1. https://github.com/jashkenas/backbone/blob/master/examples/todos/index.html 27 | -------------------------------------------------------------------------------- /src/part-2/chapter-1-模块系统/section-4-amd.md: -------------------------------------------------------------------------------- 1 | # AMD 模块系统 2 | 3 | ## 定义 4 | 5 | AMD(Asynchronous Module Definition)即**异步模块定义**。AMD 规范中,各个依赖可以异步加载而不影响正常逻辑,非常适用于浏览器环境。AMD 规范的核心 API 只有一个简单的 `define()` 函数。 6 | 7 | ```javascript 8 | function define(id?, dependencies?, factory) { 9 | // ... 10 | }; 11 | define.amd = {}; 12 | ``` 13 | 14 | AMD 模块系统的经典实现库是 require.js[1]。 15 | 16 | ## RequireJS 的基本使用 17 | 18 | 首先我们来看一下 require.js 的使用。考虑如下目录结构的静态页面服务: 19 | 20 | ``` 21 | root-dir 22 | ├── amd-demo // 示例页面 23 | │   ├── index.css 24 | │   ├── index.html // 入口页面 25 | │   └── main.js // 入口 JS 26 | ├── common.css 27 | └── js // 公共脚本目录 28 | ├── jquery-3.2.1.js 29 | ├── jquery-3.2.1.min.js 30 | ├── lodash.min.js 31 | └── require.js // 模块加载器 32 | ``` 33 | 34 | `amd-demo` 目录是我们的示例页面目录,`index.html` 如下: 35 | 36 | ```html 37 | 38 | 39 | 40 | ADM 模块系统示例 41 | 42 | 43 | 44 |

ADM 模块系统示例

45 |

 46 |   
47 | 48 | 49 | 50 | ``` 51 | 52 | ```javascript 53 | /** 54 | * /amd-demo/main.js 55 | */ 56 | requirejs.config({ 57 | paths: { 58 | 'jquery': '/js/jquery-3.2.1' 59 | } 60 | }); 61 | 62 | require([ 63 | '/js/lodash.min.js', 64 | 'jquery', 65 | ], function(_, $) { 66 | var str = 'I am using main.js, and I am loaded.'; 67 | 68 | if (_ && (typeof _.chunk === 'function')) { 69 | var res = _.chunk(['a', 'b', 'c', 'd'], 2); 70 | str += '\nLodash.js seems fine too. \n_.chunk gives this result: ' + JSON.stringify(res); 71 | } 72 | 73 | console.log(str); 74 | document.getElementById('console').innerHTML = str; 75 | 76 | if (typeof $ === 'function') { 77 | $('[data-role="jquery-container"]').html('jQuery is loaded too.'); 78 | } 79 | }); 80 | ``` 81 | 82 | 利用 require.js 进行模块加载的关键代码是: 83 | 84 | ```html 85 | 86 | ``` 87 | 88 | 这行代码在浏览器里运行,会先后发生这些事情: 89 | 90 | 1. 它首先根据指定的目录 `/js/require.js` 加载 `require.js` 91 | 2. 加载完成后,`require.js` 会在所有的 `script` 标签里寻找 `data-main` 属性指定的路径文件作为下一个将要加载的脚本,在这里,就是 `/amd-demo/main.js` 92 | 3. 开始加载 `/amd-demo/main.js`,加载后,解析并执行它,如果发现它有其他依赖,那么先加载所有的依赖(递归)并完成后,再执行 `/amd-demo/main.js` 里面 `require` 的回调函数。 93 | 94 | 页面就绪后,我们可以在渲染后的 DOM 树中看到 `` 标签里多了几个 ` 41 | 42 | 43 | ``` 44 | 45 | 上面的代码里,做了这些事情: 46 | 47 | + ① 先获取到主文档里 `id` 为 `hostElement` 的 `

` 元素 48 | + ② 然后调用 `attachShadow` 方法,将其设置为一个影子树的根节点。 49 | + ③ 在这个影子根节点下,插入 HTML 字符串,交给浏览器去生成对应的 DOM 结构。可以看到执行的效果: 50 | 51 | 52 | 53 | ### 可用元素列表 54 | 55 | 并非所有的 HTML 元素都可以托管影子树,例如常见的表单元素(``、`