├── 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 | --------------------------------------------------------------------------------