Webpack(三):使用 plugin 以及本地伺服器搭建
- 2019 年 11 月 7 日
- 筆記
使用 Plugin
banner-plugin
webpack 自帶 BannerPlugin,我們只需要在 webpack.config.js
中配置即可:
const webpack = require('webpack'); //引入 module.exports = { entry:..., output:{...}, module:{...}, resolve:{...}, plugins:[ new webpack.BannerPlugin('Created by xxx'); ] }
html-webpack-plugin
之前我們的 index.html
都是在項目的根目錄下的,這個文件最後也要打包到 dist
文件夾中。
HtmlWebpackPlugin 可以自動生成一個 已經引入bundle.js
的index.html
到 dist
文件夾中。
npm install html-webpack-plugin --save -dev
不過這個生成的文件默認是沒有模板的(只有引入的 js),所以我們要配置一下:
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入 module.exports = { entry:..., output:{...}, modules:{...}, resolve:{...}, plugins:[ new ...., new HtmlWebpackPlugin({ template:'./index.html' }) ] }
這之後,webpack 將會去 webpack.config.js
所在的文件夾尋找 index.html
文件(最初的入口文件),並將其 html 結構作為新 index.html
的模板。也就是說,最初的入口文件僅提供一個模板。
Note:
另外還要注意,前面我們說過,webpack 認為 index.html
位於 dist
中,所以導致了路徑出錯,我們是通過配置 output.publicPath
或者 url-loader.options.publicPath
來修正這個問題的。但是現在 index.html
確實位於 dist
中了,所以我們也可以把這兩個配置改回來了。
uglifyjs-webpack-plugin
壓縮 js 文件:
npm install uglifyjs-webpack-plugin@1 --save -dev
進行配置:
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin'); //引入 module.exports = { entry:..., output:{...}, modules:{...}, resolve:{...}, plugins:[ new ...., new ...., new UglifyWebpackPlugin() ] }
這裡又因為版本不匹配的問題報錯了,原因是 webpack@3 對應的 plugin 版本是 @1,所以如果 npm 安裝的時候不指定版本,默認會安裝最新的 @2 版本,後面打包就會報錯了。
Webapck 搭建本地伺服器
安裝
Webpack 提供了一個可選的本地開發伺服器,基於 node.js 搭建,內部使用 express 框架,可以實現熱更新。
文件暫緩到記憶體中,記憶體中讀取速度要比磁碟快很多,之後執行打包命令的時候才輸出到磁碟。
首先安裝一下:
npm install [email protected] --save -dev
Note:這裡也要注意和 webpack 的版本對應。
之後配置一下:
module.exports = { entry:..., output:{...}, modules:{...}, resolve:{...}, plugins:[...], devServer:{ contentBase:'./dist' // 為哪個文件夾提供本地服務 inline: true, // 開啟熱更新 port: 8080 // 默認8080埠號 open:true // 開啟伺服器後自動打開瀏覽器 historyApiFallback:... // 在 SPA 頁面中依賴 HTML5 的 history 模式 } }
處理報錯
這時候直接運行 webpack-dev-server
,會報錯:

這裡的操作,其實是試圖在項目根目錄下執行 webpack-dev-server.cmd
,但當前目錄並沒有這個這個東西,所以報錯了。這時候可能會有如下思路:
(1)
首先,webpack-dev-server.cmd
其實就位於 node_modules/.bin
文件夾中,我可以選擇直接執行 node_modules/.bin/webpack-dev-server
或者是 cd 進目錄後執行,如下圖:

這個思路應該是沒問題的,但是我實際這麼做的時候報錯了:

經過苦苦思索。。。好吧,犯了一個很傻逼的錯誤:

注意看上圖!!!路徑是用 而不是
/
。。。改用 之後就正常了。當然,是看到這個貼子 https://www.cnblogs.com/mqfblog/p/6444753.html 突然想到的。
(2)
第二個方法,全局安裝 webpack-dev-server
。這個當然沒問題了,這樣的話我不管在哪個路徑下運行指令,這個指令總能被找到。但是這個方法不推薦,因為有版本衝突問題。
(3)
第三個方法就是來到 package.json
配置一下命令:
"scripts": { "test": "echo "Error: no test specified" && exit 1", "build": "webpack", "dev":"webpack-dev-server" },
這之後執行 npm run dev
,那麼 npm script 的底層其實會做一些相應處理,自動到 node_modules/.bin
文件夾下尋找對應的 cmd 並執行。
更新緩慢
開啟本地伺服器,修改程式碼之後會發現可以自動刷新了。不過。。。
我進行到這一步的時候發現刷新大概需要 4 到 5 秒,對比使用 live server 時那種即時刷新的感覺,完全不是一個量級的好嗎!然後把前面安裝的 uglifyjs-webpack-plugin
去掉就正常了,看來是被這個插件影響到了。
這裡也可以發現,實際上我們是在開發完成後才需要用到這個插件去壓縮程式碼;相反地,webpack-dev-server
則是在開發過程中要用到,也就是說,這兩個東西的使用情境是不同的。那麼,有沒有方法可以依照使用情境把它們進行分離呢?
配置分離
- 抽取公共配置
- 分離開發環境配置和生產環境配置
在我們前面安裝的 plugin 里,webpack-dev-server
只有開發的時候用得到,uglifyjs-webpack-plugin
只有開發後用得到,其他的則是開發/生產時都要用到的,據此,我們可以在根目錄新建 build
文件夾,並將這些配置分別寫進三種類型的文件里:
dev.config.js / prod.config.js / base.config.js
形式上分離後,我們管理起來就方便了,之後藉助插件進行配置的合併:
npm install webpack-merge --save -dev
dev.config.js
:
const webpackMerge = require('webpackMerge'); const baseConfig = require('./base.config.js'); module.exports = webpackMerge(baseConfig,{ devServer:{ contentBase:'./dist', inline:true, open:true } })
prod.config.js
:
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin'); const webpackMerge = require('webpack-merge'); const baseConfig = require('./base.config.js'); module.exports = webpackMerge(baseConfig,{ plugins:[ new UglifyjsWebpackPlugin() ] })
base.config.js
:
const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry:..., output:{...}, module:{...}, resolve:{...}, plugins:[...] }
這之後我們要解決兩個問題:
首先,現在的 config 文件已經分離了,所以原先的 webpack.config.js
可以刪掉了,這裡會發現刪掉之後,原先配置的 npm script 指令失效了,所以來到 package.json
配置一下:
"scripts": { "test": "echo "Error: no test specified" && exit 1", "build": "webpack --config ./build/base.config.js", "dev": "webpack-dev-server --config ./build/base.config.js" },
加上 --config ./build/base.config.js
,也就是現在以 base.config.js
這個配置文件為準。
第二個問題,如果我們直接打包,會發現在 build
下輸出了 dist
文件夾,這是因為我們之前是這樣配置 output.path
的:
output:{ path:path.resolve(__dirname,'dist'), filename:'bundle.js' },
之前, __dirname
指向 webpack.config.js
所在的目錄,即根目錄,後面跟著 dist
,意思是打包到根目錄下的 dist
文件夾。而現在,__dirname
指向的是 base.config.js
所在的目錄,即 build
文件夾,後面跟著 dist
,意思是打包到 build
下的 dist
文件夾。
所以要修正一下路徑,改為 :
output:{ path:path.resolve(__dirname,'../dist'), filename:'bundle.js' },
之後就可以正常打包了。當然,對於小型項目的話,一個配置文件也完全足夠了。