├── build
├── .DS_Store
└── index.html
├── client
└── app.js
├── entry.js
├── foo.js
├── package.json
├── readme.md
├── server.js
└── webpack.config.js
/build/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coodoo/webpack-guide/a6aa7871f4b6029bf85ccbf0caa401ac20d9464b/build/.DS_Store
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Test
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/client/app.js:
--------------------------------------------------------------------------------
1 |
2 | // 如果有用到 generator 就要掛這個 polyfill
3 | // require('babel/polyfill');
4 |
5 |
6 | // 模擬 SPA 程式
7 | console.log( 'this is a SPA 23' );
8 |
9 | var arr = ['a', 'b'];
10 |
11 | arr.map( item => {
12 | var p = new Promise( (resolve, reject) => {
13 | setTimeout(resolve, 100);
14 | } );
15 | return 'name_' + item;
16 | })
17 |
18 | console.log( 'arr: ', arr );
19 |
20 | var [foo] = arr;
21 | console.log( 'foo: ', foo );
22 |
23 | var bar = {b:'11', c:'22'};
24 | var {cd} = bar;
25 | // var {...rest} = bar;
26 | console.log( 'coo: ', cd);
27 |
28 | /*function* zoo(){
29 | for( let i = 0; i<4; i++ ){
30 | console.log( 'i= ', i );
31 | yield i;
32 | }
33 | }
34 |
35 | let runner = zoo(), result;
36 | while( runner.next().done == false ){
37 | //
38 | }*/
39 |
40 | var foo = 'barrr'
41 | console.log( '>', `${foo}` );
42 |
43 | var t = ['a', 'b', 'c', 'd'];
44 | var [z1, z2, ...tada] = t;
45 | console.log( 'z: ', tada );
--------------------------------------------------------------------------------
/entry.js:
--------------------------------------------------------------------------------
1 |
2 | // 加上這句就會自動載入 es6 檔案並即時編譯為 es5
3 | require('babel/register');
4 |
5 | require('./foo');
6 |
7 |
--------------------------------------------------------------------------------
/foo.js:
--------------------------------------------------------------------------------
1 | let foo = 'bar';
2 | console.log( 'foo: ', foo );
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webpack-try",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start":"npm run build && webpack-dev-server",
8 | "dev":"webpack -d",
9 | "build":"webpack -p",
10 | "test": "karma"
11 | },
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "babel-core": "^5.5.4",
16 | "babel-loader": "^5.1.4",
17 | "node-libs-browser": "^0.5.2",
18 | "webpack": "^1.9.10",
19 | "webpack-dev-server": "^1.9.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
2 | ES6, webpack/babel and workflow
3 | ===============================
4 |
5 | Jeremy Lu (jeremy@pubuous.com)
6 | Jun 06, 2015
7 |
8 |
9 | # es6
10 |
11 | - 學習資源
12 |
13 | - http://babeljs.io/docs/learn-es2015/
14 |
15 | - http://babeljs.io/repl/
16 |
17 | - ES6 已更名為 ES2015
18 |
19 | - 重要指令
20 |
21 | - `let, const`
22 |
23 | - Arrow Function
24 |
25 | ```
26 | // example
27 | nums.forEach( (v, i, arr) => {
28 | if (v % 5 === 0)
29 | fives.push(v);
30 | });
31 | ```
32 |
33 | - Destructuring
34 |
35 | ```
36 | // example
37 | var arr = [1,2,3]; // a=1, b=3
38 | var [a, , b] = arr;
39 | var {b} = {a:'aa', b:'bb'};
40 | ```
41 |
42 | - Class
43 |
44 | ```
45 | // example
46 | class SkinnedMesh extends THREE.Mesh {
47 | ```
48 |
49 | - Template Strings
50 |
51 | ```
52 | // example
53 | var foo = 'bar'
54 | `${foo}`
55 | ```
56 |
57 | - Promise
58 |
59 | ```
60 | // example
61 | new Promise((resolve, reject) => {
62 | setTimeout(resolve, duration);
63 | })
64 | ```
65 |
66 | - Generator -> async, await // es7
67 |
68 | ```
69 | //example
70 | function* foo(){
71 | yield 'bar';
72 | }
73 | ```
74 |
75 | # 如何執行 es6
76 |
77 | ## nodejs
78 |
79 | - 建議至少 v0.12 或 io.js v2 以上版本
80 |
81 | - `$node --harmony --harmony-generators`
82 |
83 | - 不可靠
84 |
85 |
86 | - babel-node
87 |
88 | `$ npm i babel -g`
89 |
90 | - 要取代原本 node 指令
91 | - production server
92 |
93 | - require('babel/register')
94 |
95 | `$ npm i --save-dev babel`
96 |
97 | - 要多一個 entry.js 來 require() 其它檔案
98 |
99 |
100 | ## browser
101 | - 用 webpack 打包 js 成 bundle.js
102 | - 過程中套用 babel loader 將 es6 轉成 es5
103 |
104 | # webpack/babel
105 |
106 | - 建立 webpack.config.js 檔案
107 |
108 | - 開發時啟動 local web server
109 |
110 | - webpack-dev-server
111 |
112 | $ webpack-dev-server --progress
113 |
114 | - 執行 build
115 |
116 | - 安裝
117 | - webpack
118 | - babel-loader
119 |
120 | `$ webpack -d` // 然後訪問 http://localhost:8080
121 | `$ webpack -p` // 得到壓縮與不含 sourcemap 的 bundle.js 檔案
122 |
123 | # 良好開發手法
124 |
125 | - 程式模組化,一個功能一支 js
126 | - 使用 CommonJS 語法,別用 AMD 例如 requirejs
127 |
128 | # Workflow
129 |
130 | # 前端開發情境
131 |
132 | - dev
133 | - 開發時需要盡快將程式碼重新編譯、打包並刷新瀏覽器
134 | - 產生 sourcemap 方便在 DevTools 內除錯
135 |
136 | - build
137 | - 將專案所有 assets (js, css, html, images) 等編譯、合成、壓縮並搬到適當的位置
138 | - 例如將 100 支 js 檔案合成為一個 bundle.js
139 | - 或將 vendor/ 與 assets/ 下所有檔案搬到 build/ 目錄下
140 |
141 | - deploy
142 | - 做完 build 流程後,將封裝好的檔案上傳到遠方主機(例如 EC2)
143 | - 在遠端主機上重啟 app 與 db,做 zero-downtime deployment
144 | - 常見手法是透過 ssh + rsync 將整包目錄上傳
145 |
146 | # 常用工具
147 |
148 | - node.js
149 | - javascript 執行環境,常用於 server,但也適用在本機進行自動化工作
150 |
151 | - npm
152 | - node.js 內建的套件管理系統,有十萬筆以上套件可取用,例如 jquery, bootstrap, react 皆包含在內
153 | - 特別注意 package.json 內 scripts:{} 內的各種指令
154 |
155 | - gulp
156 | - 組建系統(build system),將專案封裝為可最終輸出的格式,通常包含大量自動化流程
157 | - 現在流行用 npm scripts 直接取代
158 |
159 | - webpack
160 | - 處理 module 相依關係
161 | - 程式碼打包器(module bundler),將多支 javascript 檔案合成一支並在過程中做轉換處理
162 |
163 | - babel
164 | - 轉換 es6 為 es5
165 | - 轉換 jsx, flow 為 es5
166 |
167 | # 常見問題
168 |
169 | - webpack 與 gulp 區別
170 |
171 | - webpack 是 bundler,將多支檔案進行編譯後結合為一份檔案,輸出為 bundle.js
172 |
173 | - gulp 是 build 工具,可自動化許多工作,將來做 Continous Integration & Deployment 很方便
174 |
175 | - webpack 與 browserify 差異
176 |
177 | - browserify 先出來,是老牌好用的 bundle 工具
178 |
179 | - 但 webpack 俱備下列優勢
180 |
181 | - 可輕易切分多個 bundle,並在需要時自動載入
182 | - multiple entry point
183 | - bundle.js ← 原本 3MB 的檔案,可切成三份小的檔案
184 | - main.js
185 | - b.js
186 | - c.js
187 |
188 | - 支援 Hot Module Replacement 僅更新部份頁面內容
189 | - 由於不是整頁更新,因此可保留程式狀態,方便測試
190 | - 跟 react 搭配更強大
191 |
192 | - 提供簡易的 local web server 方便開發
193 |
194 | $ webpack-dev-server // 即可訪問 http://localhost:8080
195 |
196 | - npm 與 bower 的差異
197 | - bower 是 twitter 推出
198 | - 專用於前端套件管理
199 | - 但後來 npm 內也有大量前端套件
200 | - 人們希望用一個套件管理程式就兼顧前/後端,因此 npm 勝出成為主流
201 |
202 | - CommonJS 與 RequireJS 的差異
203 |
204 | - requirejs 語法醜,東西一大時難管理
205 |
206 | // 如果 require 20 支程式,後面 function 就要依序列20個參數,缺一不可
207 | var js = require(['a', 'b', 'c', function(a, b, c){
208 | //
209 | });
210 |
211 | - requirejs config 難懂
212 | - 也不利於與各種 testing framework 整合
213 |
214 | - CommonJS 的優點
215 | - 語法簡潔
216 | - node.js 通用多年
217 | - 有 webpack 幫忙 bundle,用於 browser 內毫無困難
218 |
219 | - 什麼是 Continous Integration & Deployment (CI, CD)
220 |
221 | - CI: 每次有人 commit 就自動跑所有 test 確保都通過
222 |
223 | - CD: 每次 commit 通過 CI 測試後,自動佈署到 server 上
224 |
225 | - "deploy on green"
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 |
2 | console.log( 'server run' );
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var Path = require("path");
2 | // var webpack = require('webpack');
3 |
4 | //
5 | module.exports = {
6 |
7 | // 將來生成 bundle.js
8 | entry: {
9 | bundle: [ "./client/app.js"]
10 | },
11 |
12 | // 主要是啟動 babel-loader
13 | module: {
14 |
15 | loaders: [
16 | {
17 | test: /\.jsx?$/,
18 | exclude: [ /node_modules/, /vendor/ ],
19 | loaders: [ 'babel-loader' ]
20 | },
21 |
22 | {
23 | test: /\.css$/,
24 | loader: "style-loader!css-loader"
25 | }
26 | ],
27 |
28 | noParse: ['react', 'jquery', 'bootstrap']
29 | },
30 |
31 | output: {
32 | path: Path.resolve(__dirname, "./build"),
33 |
34 | // 有 multiple entry point 時,這裏一定要用變數寫法,不然多個產出 js file 會彼此覆寫
35 | filename: "[name].js",
36 | },
37 |
38 | // 生成 sourcemaps
39 | // 這是給 webpack-dev-server 看的參數
40 | // 一般生成 production 檔案時會用 webpack -p 就不會吐出 sourcemaps
41 | devtool: 'eval', //'#source-map'
42 |
43 | // 這是 webpack-dev-server 會看的 config
44 | // 有加這段的話,平常在 cli 跑 $ webpack-dev-server 時就不需另外加 --content-base .build/ 這參數
45 | devServer: {
46 |
47 | // 要寫絕對路徑
48 | contentBase: Path.resolve(__dirname, "./build"),
49 |
50 | // 下面三個永遠存在
51 | filename: '[name].js',
52 | publicPath: '/',
53 | outputPath: '/',
54 |
55 | // 啟動 livereload 功能
56 | // 等於是 cli 時有無下 --inline 參數
57 | inline: true,
58 |
59 | // webpack-dev-middleware options
60 | quiet: true, // 設為 true 即不會顯示太多 debug 訊息,讓 console 乾淨一點
61 | noInfo: true,
62 | lazy: false, // false 是啟動 watch mode,有變化即自動編譯
63 | stats: { colors: true, cached: false, cachedAssets: false },
64 |
65 | }
66 |
67 | };
68 |
--------------------------------------------------------------------------------