Webpack(三):使用 plugin 以及本地伺服器搭建

  • 2019 年 11 月 7 日
  • 筆記

使用 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.jsindex.htmldist 文件夾中。

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'    },

之後就可以正常打包了。當然,對於小型項目的話,一個配置文件也完全足夠了。