鑑於webpack更新太快,總結下基礎配置方法,理解有限,僅作拋磚引玉之用。javascript
初始化配置文件 package.json
並安裝webpackcss
mkdir webpack-demo && cd webpack-demo npm init -y //-y 初始化選項默認爲 yes npm i webpack webpack-cli -D // -D 即 -save-dev 版本4.x以上須要安裝webpack-cli
建立如下目錄結構、文件和內容:html
webpack-demo |- package.json + |- /src + |- index.js
//index.js document.write("Hello webpack4!");
編寫開發環境和生產環境彼此獨立的webpack配置文件
先添加三個文件java
webpack-demo |- package.json + |- webpack.common.js + |- webpack.dev.js + |- webpack.prod.js |- /src |- index.js |- /node_modules
1.webpack.common.js
node
用到兩個基本的插件react
npm i clean-webpack-plugin html-webpack-plugin -D
clean-webpack-plugin
:打包時自動清除輸出文件夾中未用到的文件;html-webpack-plugin
:打包時會自動生成index.html
並替換已有的index.html
,bundle.js也會自行添加到 html 中。webpack
//webpack.common.js const path = require('path'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.js', plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'index' }) ], output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') //定義輸出文件夾dist路徑 } };
2.webpack.dev.js
es6
先安裝webpack-merge,用以合併通用配置文件與開發環境配置文件web
npm i webpack-merge -D
安裝開發服務器devServer
,做用是修改代碼後實時從新加載(刷新瀏覽器)npm
npm i webpack-dev-server -D
//webpack.dev.js const merge = require('webpack-merge'); const common = require('./webpack.common.js'); const webpack = require('webpack'); module.exports = merge(common,{ devServer: { //啓用開發服務器 contentBase: './dist', //告訴服務器從哪提供內容,只有在想要提供靜態文件時才須要 compress: true, //一切服務都啓用gzip 壓縮 host: '0.0.0.0', //指定使用一個host,可用ip地址訪問,沒有的話若是別人訪問會被禁止。默認localhost。 port: '9999', //指定端口號,如省略,默認爲」8080「 hot: true, //啓用模塊熱替換特性 inline: true, //啓用內聯模式,一段處理實時重載的腳本被插入到bundle中,而且構建消息會出如今瀏覽器控制檯 historyApiFallback: true,//開發單頁應用時有用,依賴於HTML5 history API,設爲true時全部跳轉將指向index.html }, plugins: [ new webpack.HotModuleReplacementPlugin(), //webpack內置的熱更新插件 ], mode: 'development' });
devServer的更多可選參數-https://www.webpackjs.com/con...
HotModuleReplacementPlugin
模塊熱替換(Hot Module Replacement)插件,用以在運行時更新發生改變的模塊,從而無需進行徹底刷新。
3.webpack.prod.js
一樣用'webpack-merge'合併通用配置文件與生產環境配置文件
//webpack.prod.js const merge = require('webpack-merge'); const common = require('./webpack.common.js'); module.exports = merge(common,{ mode: "production" });
關於
mode
此時你可能會注意到配置文件中有個mode項,webpack4中新加,做用以下:
--mode production 生產環境
不須要像舊版本同樣定義node環境變量 new webpack.DefinePlugin({"process.env.NODE_ENV":JSON.stringify("production") })
ps:許多 library 將經過與 process.env.NODE_ENV 環境變量關聯,以決定 library 中應該引用哪些內容。當使用 process.env.NODE_ENV === 'production' 時,一些 library 可能針對具體用戶的環境進行代碼優化,從而刪除或添加一些重要代碼。
自動開啓一些插件,如:uglifyjs-webpack-plugin
js代碼壓縮(因此無需再單獨使用)NoEmitOnErrorsPlugin
編譯出錯時跳過輸出,以確保輸出資源不包含錯誤ModuleConcatenationPlugin
webpack3 添加的做用域提高(Scope Hoisting)
自行定義node環境變量爲development new webpack.DefinePlugin({"process.env.NODE_ENV":JSON.stringify("development") })
使用 eval 構建 module, 提高增量構建速度
自動開啓一些插件,如NamedModulesPlugin
使用模塊熱替換(HMR)時會顯示模塊的相對路徑
具體描述:
Option | Description |
---|---|
development | Sets process.env.NODE_ENV to value development. Enables NamedChunksPlugin and NamedModulesPlugin. |
production | Sets process.env.NODE_ENV to value production. Enables FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin and UglifyJsPlugin. |
none | Opts out of any default optimization options |
在package.json
"scripts" 中添加npm腳本,從而快捷運行開發服務器 | 打包生產環境代碼
//package.json { "name": "webpack-demo", "version": "1.0.0", "description": "", "private": true, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open --config webpack.dev.js", "build": "webpack --config webpack.prod.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "clean-webpack-plugin": "^0.1.19", "html-webpack-plugin": "^3.2.0", "webpack": "^4.15.1", "webpack-cli": "^3.0.8", "webpack-dev-server": "^3.1.4", "webpack-merge": "^4.1.3" } }
"start": "webpack-dev-server --open --config webpack.dev.js",
webpack-dev-server 啓動開發服務器 --open 打開瀏覽器 --config webpack.dev.js 設置運行此腳本時執行的配置文件爲webpack.dev.js
"build": "webpack --config webpack.prod.js"
webpack 啓動webpack --config webpack.prod.js 設置運行此腳本時執行的配置文件爲webpack.prod.js
執行 npm start
此時應該能夠看到 Hello webpack4!
執行 npm run build
項目文件夾中自動生成打包後的文件目錄(輸出文件夾dist)
webpack-demo |- package.json |- webpack.common.js |- webpack.dev.js |- webpack.prod.js |- /src |- index.js |- /dist | - index.html | - app.bundle.js |- /node_modules
sourcemap 能實現打包後的運行代碼與源代碼的映射,幫助咱們debug到原始開發代碼。
///webpack.dev.js module.exports = merge(common,{ devtool: 'cheap-module-eval-source-map', ... });
大多數時候開發環境用'cheap-module-eval-source-map'是最好的選擇,想要完整的功能又不介意構建速度的話就直接用'source-map'。具體的配置項不少,能夠是eval,source-map,cheap,module,inline的任意組合。
具體每一個參數的做用請查閱官方api:https://webpack.js.org/config...
也可參考這篇文章https://segmentfault.com/a/11... 這裏不作詳述。
把代碼分離到不一樣的 bundle 中,能夠按需加載或並行加載這些文件。可用於獲取更小的 bundle,以及控制資源加載優先級,若是使用合理,會極大影響加載時間。
三種經常使用的代碼分離方法:
1.入口起點:使用 entry 配置手動地分離代碼。
先在src文件夾添加一個文件another-module.js
//another-module.js import _ from 'lodash'; console.log( _.join(['Another', 'module', 'loaded!'], ' ') );
修改index.js
//index.js import _ from 'lodash'; console.log( _.join(['index', 'module', 'loaded!'], ' ') );
用到了lodash,安裝下依賴
npm i lodash -S
修改webpack.common.js中entry和output配置
//webpack.common.js module.exports = { entry: { index: './src/index.js', another: './src/another-module.js' }, output: { filename: '[name].bundle.js', //根據入口文件名來定義輸出文件名 path: path.resolve(__dirname, 'dist') } };
執行 npm run build
將生成以下構建結果:
Hash: 66f57fffc46778f3b145 Version: webpack 4.16.0 Time: 2966ms Asset Size Chunks Chunk Names another.bundle.js 70.4 KiB 0 [emitted] another index.bundle.js 70.4 KiB 1 [emitted] index index.html 251 bytes [emitted] [1] (webpack)/buildin/module.js 497 bytes {0} {1} [built] [2] (webpack)/buildin/global.js 489 bytes {0} {1} [built] [3] ./src/another-module.js 86 bytes {0} [built] [4] ./src/index.js 83 bytes {1} [built] + 1 hidden module Child html-webpack-plugin for "index.html": 1 asset [0] (webpack)/buildin/module.js 497 bytes {0} [built] [1] (webpack)/buildin/global.js 489 bytes {0} [built] + 2 hidden modules
存在的問題:
以上兩點中,第一點對咱們的示例來講無疑是個問題,index.js 和another-module.js中都引入了 lodash,這樣就在兩個 bundle 中形成重複引用。接着,咱們經過使用 SplitChunks 來移除重複的模塊。
2.防止重複:使用SplitChunks
去重和分離 chunk。webpack4 以前版本用的是CommonsChunkPlugin
//webpack.common.js const path = require('path'); module.exports = { entry: { index: './src/index.js', another: './src/another-module.js' }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Production' }) ], output: { filename: '[name].bundle.js', //根據入口文件名來定義輸出文件名 path: path.resolve(__dirname, 'dist') }, + optimization: { + splitChunks: { + chunks: 'all' + } + } };
再次執行npm run build查看效果
... vendors~another~index.bundle.js 69.5 KiB 0 [emitted] vendors~another~index another.bundle.js 1.54 KiB 1 [emitted] another index.bundle.js 1.54 KiB 2 [emitted] index ...
觀察打包後文件大小,能夠看到index.bundle.js
和another.bundle.js
中已經移除了重複的依賴模塊。lodash 被分離到單獨的vendors~another~index.bundle.js
chunk中。
3.動態導入:經過模塊的內聯函數調用來分離代碼。
略~。~
須要用到插件mini-css-extract-plugin
,這個插件會將提取css到單獨的文件,根據每一個包含css的js文件建立一個css文件,所以,你的樣式將再也不內嵌到 JS bundle 中。若是你的樣式文件大小較大,這會作更快提早加載,由於 CSS bundle 會跟 JS bundle 並行加載。同時還支持按需加載css和SourceMaps.
相較於舊版extract-text-webpack-plugin
插件,mini-css-extract-plugin
的優點有
npm i mini-css-extract-plugin -D
//webpack.common.js const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { ... plugins: [ new MiniCssExtractPlugin({ filename: "[name].css", }) ], module: { rules: [ { test: /\.css$/, use: [ { loader: MiniCssExtractPlugin.loader, options: { publicPath: '../' //能夠配置輸出的css文件路徑 } }, "css-loader" ] } ] } ... }
注意
,這個插件不兼容style-loader
(用於以<style>標籤形式將css-loader內部樣式注入到HTML頁面)。
若是想在開發環境下使用style-loader
,在生產環境分離css文件,能夠這麼配置:
//webpack.common.js const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const devMode = process.env.NODE_ENV !== 'production' module.exports = { plugins: [ new MiniCssExtractPlugin({ filename: '[name].css', }) ], module: { rules: [ { test: /\.(sa|sc|c)ss$/, use: [ devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 'css-loader', { loader:"postcss-loader", //本文未用到此loader... options: { // 若是沒有options這個選項將會報錯 No PostCSS Config found plugins: (loader) => [] } }, 'sass-loader', ], } ] } }
很明顯咱們須要先安裝處理樣式文件的各類loader
npm i style-loader css-loader postcss-loader node-sass sass-loader -D
這裏有個問題,node環境變量process.env.NODE_ENV在webpack.config中實際上是undefined,以前說起的mode配置會自動定義這個環境變量,但只能在打包後的js中取到,如何在webpack的配置文件中獲取這個值呢,須要引入cross-env
npm i cross-env -D
而後在package.json
的腳本命令中指定環境變量
"start": "cross-env NODE_ENV=development webpack-dev-server --open --config webpack.dev.js", "build": "cross-env NODE_ENV=production webpack --config webpack.prod.js"
可自行添加css文件,在js中import,執行npm run build查看效果
固然也能夠不獲取process.env.NODE_ENV
來區分環境,在dev.js和prod.js分別配置處理樣式文件的rule就好了,這也是最開始咱們分開寫開發環境和生產環境的webpack配置文件的緣由。這裏說起只是方便從低版本webpack遷移到4.x。
在單個文件中提取全部CSS
配合optimization.splitChunks.cacheGroups使用
//webpack.common.js optimization: { splitChunks: { cacheGroups: { styles: { name: 'styles', test: /\.css$/, chunks: 'all', enforce: true } } } }
會額外生成一個styles.bundle.js
按照入口JS來分離css
//webpack.common.js ... function recursiveIssuer(m) { if (m.issuer) { return recursiveIssuer(m.issuer); } else if (m.name) { return m.name; } else { return false; } } module.exports = { entry: { index: './src/index.js', another: './src/another-module.js' }, ... optimization: { splitChunks: { cacheGroups: { vendor: { //分離第三方庫 test: /[\\/]node_modules[\\/]/, name: 'lodash', chunks: 'all' }, indexStyles: { name: 'index', test: (m,c,entry = 'index') => m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry, chunks: 'all', enforce: true }, otherStyles: { name: 'another', test: (m,c,entry = 'another') => m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry, chunks: 'all', enforce: true } } } } };
壓縮css
webpack5可能會內置CSS壓縮,webpack4須要使用像optimize-css-assets-webpack-plugin
這樣的插件。有個問題是設置optimization.minimizer後,會覆蓋上文提到的mode配置項提供的默認值,所以須要同時使用JS壓縮插件UglifyJsPlugin
npm i optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin -D
//webpack.prod.js const merge = require('webpack-merge'); const common = require('./webpack.config.js'); const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); module.exports = merge(common,{ mode: "production", optimization: { minimizer: [ new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true // set to true if you want JS source maps }), new OptimizeCSSAssetsPlugin({}) ], } });
咱們都知道瀏覽器獲取資源是比較耗費時間的,因此它會使用一種名爲 緩存 的技術。經過命中緩存,以下降網絡流量,使網站加載速度更快。若是咱們在部署新版本時不更改資源的文件名,瀏覽器就可能會認爲它沒有被更新,就會使用它的緩存版本。所以確保 webpack 編譯生成的文件可以被客戶端緩存,而在文件內容變化後,可以請求到新的文件是頗有必要的。
經過使用 output.filename
進行文件名替換,能夠確保瀏覽器獲取到修改後的文件。[hash]
替換能夠用於在文件名中包含一個構建相關的hash,可是更好的方式是使用[chunkhash]
替換,在文件名中包含一個 chunk相關的hash。遺憾的是chunkhash和熱更新不兼容,因此開發環境和生產環境要分開配置。
//webpack.common.js ... output: { filename: devMode ? '[name].[hash:8].js': '[name].[chunkhash:8].js', //數字8表示取hash標識符的前八位 chunkFilename: devMode ? '[name].[hash:8].js': '[name].[chunkhash:8].js', //異步模塊的文件輸出名 path: path.resolve(__dirname, 'dist') }, ...
關於[hash]
和[chunkhash]
的區別,簡單來講,[hash]
是編譯(compilation)後的hash值,compilation
對象表明某個版本的資源對應的編譯進程。項目中任何一個文件改動,webpack就會從新建立compilation
對象,而後計算新的compilation的hash值,全部的編譯輸出文件名都會使用相同的hash指紋,改一個就一塊兒變。而[chunkhash]
是根據具體模塊文件的內容計算所得的hash值,某個文件的改動只會影響它自己的hash指紋,不會影響其餘文件。
上文代碼分離一節中已經提到了如何將第三方庫(好比lodash或react)提取到單獨的vendor chunk文件中,由於它們不多像本地的源代碼那樣頻繁修改。利用客戶端的長效緩存機制,能夠消除請求,減小向服務器獲取資源,同時還能保證客戶端代碼和服務器端代碼版本一致。
除了第三方庫,webpack在入口模塊中,包含了某些樣板(boilerplate)
,確切來講就是runtime
和 manifest
。即webpack運行時的引導代碼,這部分代碼咱們也將它單獨提取出來。
//webpack.common.js ... optimization: { runtimeChunk: 'single', //分離webpack運行時的引導代碼 splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all' } } } } ...
咱們刪掉another-module.js
,修改index.js
以下
///index.js import _ from 'lodash'; function component() { var element = document.createElement('div'); // Lodash, now imported by this script element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } document.body.appendChild(component());
執行npm run build
產生如下輸出:
Hash: 131e8681e4403392cb5d Version: webpack 4.16.1 Time: 744ms Asset Size Chunks Chunk Names index.5bc56cae.js 260 bytes 0 [emitted] index vendors.5d8f5a63.js 69.5 KiB 1 [emitted] vendors runtime.eb6eb2fb.js 1.42 KiB 2 [emitted] runtime index.html 316 bytes [emitted] [1] ./src/index.js 253 bytes {0} [built] [2] (webpack)/buildin/global.js 489 bytes {1} [built] [3] (webpack)/buildin/module.js 497 bytes {1} [built] + 1 hidden module Child html-webpack-plugin for "index.html": 1 asset [2] (webpack)/buildin/global.js 489 bytes {0} [built] [3] (webpack)/buildin/module.js 497 bytes {0} [built] + 2 hidden modules
能夠看到編譯出的文件名後加上了hash,運行時的引導代碼也被單獨提取出來了。
接着添加一個print.js
///print.js export default function print(text) { console.log(text); };
修改index.js
///index.js import _ from 'lodash'; + import Print from './print'; function component() { var element = document.createElement('div'); // Lodash, now imported by this script element.innerHTML = _.join(['Hello', 'webpack'], ' '); + element.onclick = Print.bind(null, 'Hello webpack!'); return element; } document.body.appendChild(component());
再執行npm run build
構建結果以下:
Hash: a710a54674ea8d4b3263 Version: webpack 4.16.1 Time: 3328ms Asset Size Chunks Chunk Names index.15466585.js 327 bytes 0 [emitted] index vendors.7bde7828.js 69.5 KiB 1 [emitted] vendors runtime.eb6eb2fb.js 1.42 KiB 2 [emitted] runtime index.html 316 bytes [emitted] [1] (webpack)/buildin/global.js 489 bytes {1} [built] [2] (webpack)/buildin/module.js 497 bytes {1} [built] [3] ./src/index.js + 1 modules 406 bytes {0} [built] | ./src/index.js 337 bytes [built] | ./src/print.js 64 bytes [built] + 1 hidden module Child html-webpack-plugin for "index.html": 1 asset [2] (webpack)/buildin/global.js 489 bytes {0} [built] [3] (webpack)/buildin/module.js 497 bytes {0} [built] + 2 hidden modules
咱們指望的是,只有 index bundle 的 hash 發生變化,然而vendors也跟着變了。這是由於每一個 module.id 會基於默認的解析順序(resolve order)進行增量。也就是說,當解析順序發生變化,ID 也會隨之改變。(官方文檔裏說runtime的hash也發生了變化,這裏並未出現)
可使用兩個插件來解決這個問題。一是NamedModulesPlugin
,將使用模塊的路徑而不是數字標識符。此插件有助於在開發過程當中輸出結果的可讀性,但執行時間會長一些。二是使用webpack內置插件HashedModuleIdsPlugin
,推薦用於生產環境構建:
const webpack = require('webpack'); ... module.exports = { ... plugins: [ ... new webpack.HashedModuleIdsPlugin(), ... ], ... };
接下來,咱們能夠隨意修改index.js的代碼或者增刪print.js,再進行構建查看hash的變化。
關於css緩存
假如index.js引用了一個index.css文件,它們會共用相同的chunkhash值。這時若是index.js更改了代碼,index.css文件就算內容沒有任何改變也會重複構建。
咱們可使用MiniCssExtractPlugin
裏的contenthash
,保證css文件所處的模塊裏只要css文件內容不變,其自己就不會重複構建。
new MiniCssExtractPlugin({ filename: "[name].[contenthash:8].css", chunkFilename: "[name].[contenthash:8].css" }),
這樣基本就完成了webpack的緩存配置。
有個小問題是,當修改index.css文件代碼,從新構建後index.js的hash值也一塊兒改變了。。。
嘗試了下安裝插件WebpackMd5Hash能夠解決
npm i webpack-md5-hash -D
but,這個插件可能會引起別的bug,好吧這裏先不用,後續補充,有興趣可自行搜索
完成了基本的配置文件編寫與代碼分離,開發中須要用babel將舊的瀏覽器或環境中的es 2015+代碼轉換爲es5。
須要安裝一些依賴。
babel-core //必備的核心庫 babel-loader //webpack loader配置必備 babel-preset-env //支持es201五、201六、2017, babel-preset-stage-0 //默認向後支持 stage-1,stage-2,stage-3, babel-runtime babel-plugin-transform-runtime //轉譯新的API
npm i babel-runtime -S
npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 babel-plugin-transform-runtime -D
建立.babelrc
文件
///.babelrc { "presets": [ "env", "stage-0" ], "plugins": [ ["transform-runtime", { "helpers": false, //建議爲false "polyfill": false, //是否切換新的內置插件(Promise,Set,Map等)爲使用非全局污染的 polyfill,根據你的網站兼容性狀況來看,開啓會增長不少額外的代碼 "regenerator": true //是否切換 generator 函數爲不污染全局做用域的 regenerator runtime。 }], ] }
關於 babel-polyfill 與 babel-plugin-transform-runtime
babel 能夠轉譯新的 JavaScript 語法,但並不會轉化BOM裏面不兼容的API好比Promise,Set,Symbol,Array.from,async 等。這時就須要 polyfill(軟墊片) 來轉化這些API
babel-polyfill
會仿效一個完整的 ES2015+ 環境,這樣你就可使用新的內置對象好比 Promise 或WeakMap, 靜態方法好比 Array.from 或者 Object.assign, 實例方法好比 Array.prototype.includes 和生成器函數(提供 regenerator 插件)。babel-polyfill
缺點是它經過改寫全局prototype的方式實現,會污染全局對象因此不適合第三方庫的開發,且打包後代碼冗餘量比較大,咱們可能不須要用到全部的新API,對於現代瀏覽器有些也不須要polyfill。
babel-plugin-transform-runtime
依賴babel-runtime
,babel編譯es6到es5的過程當中,babel-plugin-transform-runtime
會自動polyfill es5不支持的特性,這些polyfill包就是在babel-runtime這個包裏(這就是爲啥babel-runtime
須要做爲生產依賴引入(使用 --save))。transform-runtime優勢是不會污染全局變量,屢次使用只會打包一次,而且統一按需引入依賴,無重複、多餘引入。缺點是例如"foobar".includes("foo")等實例方法將不起做用。
以react開發爲例,若是是搭建新的項目,能夠直接安裝官方腳手架create-react-app
或者使用阿里的開源ui框架 Ant Design
這裏僅僅提一下如何在webpack中配置react開發環境
npm install react react-dom -S
還須要安裝
babel-plugin-transform-decorators-legacy //支持修飾符語法 @connect babel-preset-react //解析react語法 react-hot-loader //react熱更新須要在babelrc作配置
///.babelrc { "presets": [ "env", "react", "stage-0" ], "plugins": [ ["transform-runtime", { "helpers": false, //建議爲false "polyfill": false, //是否開始polyfill,根據網站兼容性決定是否開啓 "regenerator": true }], "react-hot-loader/babel", //react熱更新插件 "transform-decorators-legacy" //修飾符語法轉換插件 ] }
若是以前webpack-dev-server配置正確,這時只要把你的根組件標記爲熱導出,就能啓用react熱更新
///index.js import React from 'react'; import { hot } from 'react-hot-loader'; const App = () => <div>Hello World!</div> export default hot(module)(App);
別忘了配置babel-loader
///webpack.common.js module: { rules: [{ test: /\.jsx?$/, use: 'babel-loader' }] }
未完待續,容老夫喝口水先...