概述,在webpack裏面有四個概念: 入口、出口、插件和loader,進行模塊化打包,支持CMD、ADM、commonJS、import等模塊化操做。css
安裝說明:在webpack安裝的時候,須要先安裝一個全局的webpack,而後在須要的文件夾中安裝局部的依賴,webpack webpack-cil腳手架,在webpack3的版本中,它們是集成在一塊兒。本次筆記是針對於:webpack4.x以上的版本html
npm install webpack -g //先安裝全局的webpack,安裝完成後,才能夠實驗webpack命令,直接打包
npm install webpack webpack-cli -D // 在須要的目錄安裝webpack
webpack // 在cmd或者vscode中運行這個,就能夠打包了,其它的配置,且看後面
複製代碼
安裝完成後,須要在項目根目錄新建一個
webpack-config.js
的配置文件;沒有新建這個文件,也能夠打包,由於webpack
有默認配置。前端
若是沒有安裝全局webpack的話,就沒法直接使用webpack直接打包,固然,也能夠單獨是配置腳本,例:vue
scripts: {
dev: webpack --config webpack-config.js
}
複製代碼
在4.0之後的版本里面,新增了一個多入口打包命令:webpack app.js app1.ja -o bulid.jsnode
在webpack中有生產模式(production)和開發模式(development),默認爲開發設置,用,mode參數去設置模式,例:react
module.exports = {
mode: 'production' // 模式選擇,生產和開發兩種
};
複製代碼
特別說明:須要指定mode屬性,否則控制檯會報出一個警告信息jquery
入口(entry point),表示 webpack
應該使用哪一個模塊;進入入口之後,webpack 會找出有哪些模塊和庫是入口起點(直接和間接)依賴的。webpack
入口能夠是單入口和多入口(使用一個數組或者對象表示),在實際操做中,爲了便於優化以及首屏加載問題,會更傾向於第三種方式,既對象的形式。ios
可是使用對象寫法(
entry
代碼分離),會有一些小問題;假設entry
引入了2個js
文件,分別是a.js
和b.js
,可是這個兩個文件都引入了同一個依賴,打包之後,就會形成代碼重複,很是不利於優化,因此須要使用SplitChunksPlugin
來進行防止重複或者是動態倒入的方法。點擊查看這種方式的坑點:代碼分離。git
module.exports = {
entry: './app.js' // 寫法一
entry: ['./app.js, main.js'] //寫法二
entry: {
app: './app.js',
main: './main.js'
} //寫法三
};
複製代碼
若是使用(output)屬性表示,這個屬性是用來告訴webpack輸出它所建立的內容,默認的目錄是dist文件夾,在項目的根目錄中,也能夠指定一個目錄導出。
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js', // 入口
output: { // 出口
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js' // 單文件合併的寫法
filename: '[name].js', // 多入口多文件
chunkFilename: [name][contenthash].js, // 防止緩存,只有在更新之後纔會生成隨機碼
publicPath: 'CDN地址' // 設置CDN服務器地址, 理論上是能夠直接打包到CDN服務器上,前提是有權限
}
};
複製代碼
入口文件有配置的,就走filename
這個屬性,若是是其它文件導入的,就走下面這個,既chunkFilename
,在使用的時候,目的就是解決代碼更新,而瀏覽器讀取緩存獲取不到更新。
在output中,filename屬性是用來告訴webpack打包後的文件名稱;而path是告訴webpack須要建立的文件夾的位置信息,這個要調用node裏面一個模塊,既path模塊,__dirname是node裏面的一個關鍵字,表示路徑,絕對路徑
提示:在webpack裏面,多個入口若是要合併文件,只能使用數組的方式; 若是須要打包多文件的時,入口須要使用對象,出口使用一個動態的寫法,如上代碼"多入口文件", [name].js,若是入口是一個對象,出口必定是一個動態寫法,不然就會致使打包不正常。
loader 讓 webpack 可以去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 能夠將全部類型的文件轉換爲 webpack 可以處理的有效模塊,而後你就能夠利用 webpack 的打包能力,對它們進行處理。
loader的執行順序,是從下到上,從右到左的執行順序,因此在設置loader的時候,順序不能放錯,不然,可能會致使打包異常。
我的理解: loader就至關因而一個翻譯器,將咱們寫的代碼,進行翻譯並處理。使用方法,以下:babel爲例
注意:在lodaer裏面,配置正則(test)的時候,必定不能加引號,不然會提示lodaer錯誤。
介紹:babe就是將ES6轉成ES5的一個編譯器,須要安裝3個依賴;雖然Babel能夠將ES6的語法轉成ES5的語法,可是若是是ES6+裏面的內置API就沒法去轉換了,所以安裝一個墊片@babel/polyfill,它主要是爲了兼容低版本的瀏覽器,
babel-loader @babel/core // 主要是語法轉換
@babel/preset-env // 這個用來指定ES的版本
@babel/polyfill // 全局墊片,用於轉換內置API支持ES5的語法
/* 局部墊片須要安裝的依賴項 */
@babel/plugin-transform-runtime
@babel/runtime
複製代碼
module: {
rules: [
{
test: /\.m?js$/, // 匹配文件的後綴名
exclude: /(node_modules|bower_components)/, // 須要剔除的目錄
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'], // 墊片使用
plugins: ['@babel/plugin-proposal-object-rest-spread'] //額外的
}
}
}
]
}
複製代碼
關於屬性use的操做,若是配置項目不是不少的時候,能夠不用use這個屬性,它們兩個是等價的,直接寫,例:
rules: [{
test: /\.m?js$/, // 匹配文件的後綴名
loader: 'babel-loader', // 加載的loader
exclude: /(node_modules|bower_components)/, // 須要剔除的目錄
options: { //配置項
presets: ['@babel/preset-env'], // 默認寫法,不使用配置的寫法
presets: [["@babel/preset-env", { // 第二種寫法,配置一個babel/polyfill墊片
useBuiltIns: "usage", // 按需加載 entry | usage
targets: {
chrome: "68" // 瀏覽器目標,也能夠跟隨一個瀏覽器的市場份額
}
}]
]
}
}]
複製代碼
關於@babel/polyfill
的使用:先安裝,須要在被打包的文件中引入 @babel/polyfill
這個模塊,默認是會打包全部的API內置模塊,所以須要一個按需加載,寫法:useBuildIns: 'usage'
。
默認會報出一個警告,解決方案:若是配置了usage
的話,就不須要在被打包的文件種引入@babel/polyfill
,若是須要引入的話:則須要用entry
替換(局部方式,按照文件需求)
關於局部墊片的使用說明:若是是寫的一個插件,就不能使用全局墊片,使用局部墊片須要有兩個依賴@babel/plugin-transform-runtime
和@babel/runtime
。
在項目根目錄須要新建一個單文件,文件名:.babelrc
,格式是一個標準的JSON,因此須要使用標準的JSON格式,下面已局部墊片配置爲例:
{
"presets":["@babel/preset-env"],
"plugins": [["@babel/plugin-transform-runtime", {
"absoluteRuntime": false,
"corejs": 2, // corjs須要改爲2,不改的話會形成打包異常,官方默認是false,可選數字和布爾
"helpers": true,
"regenerator": true,
"useESModules": false
}]
]
}
/* ================ 正常模式下 使用文件名的方式 配置 ========================*/
{
"presets": [["@babel/preset-env", {
"useBuiltIns": "usage",
"targets": {
"chrome": "68" // 瀏覽器目標,也能夠跟隨一個瀏覽器的市場份額,也能夠是:last 100 versions
}
}]
]
}
複製代碼
關於異常的處理:corejs
官方的默認值是false,可是這樣會有異常,結果就是不會轉換;所以在corejs
的屬性後面要跟上一個數字2,可是這樣,仍是不行,所以須要下載一個@babel/runtime-corejs2
依賴項,用來改變以前的@babel/runtime
注意:在設置presets屬性的時候,若是須要配置,第二個對象是放在嵌套數組裏面,如:
[['xxx',{} ]]
,而且,不能夠在在webpack裏面設置了之後,再去單獨的.babelrc
裏面去設置,根據試驗證實:會報錯。
想要使用一個插件,你只須要
require()
它,而後把它添加到plugins
數組中。多數插件能夠經過選項(option)自定義。你也能夠在一個配置文件中由於不一樣目的而屢次使用同一個插件,這時須要經過使用new
操做符來建立它。
這是官方的說法,我本身的理解就是,給webpack擴展一個功能,這個功能極其強大,能夠用來處理各類各樣的任務,插件的使用方法以下:
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 經過 npm 安裝的模塊
const webpack = require('webpack'); // 用於訪問內置插件
const path = require('path') //這是一個文件路徑的內置模塊,在使用resolve屬性時,就必需要有這個
const config = { // 多文件配置的寫法
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
};
module.exports = config
複製代碼
HtmlWebpackPlugin插件,該插件將爲你生成一個 HTML5 文件, 其中包括使用 script
標籤的 body 中的全部 webpack 包。 使用的時候,須要安裝這個插件html-webpack-plugin
,基本具體配置以下:
var HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入插件
plugins: [
new HtmlWebpackPlugin({ // 能夠配置更多的值,好比title
title: 'webpack', // 生成HTML標題
templat: './index.html' // 配置的模板文件
hash: true, // 防止緩存,給生成的JS文件添加一個hash值,包含css
cache: true // 僅在內容被更改時才更新文件
inject: true, // JS注入的位置,true,默認底部
chunks:['xxx', 'entry入口文件名'], // 多入口文件,會根據配置生成JS文件,默認所有引用
minify: {
removeAttributeQuotes: true, // 是否移除屬性的引號 默認false
}
})
]
複製代碼
參考資料: npm原文連接、webpack4 之html-webpack-plugin。更多配置查看前面的NPM原文連接
clean-webpack-plugin插件能對配置的輸出文件進行清除,在build
命令開始執行的時候,會自動的去檢查,若有有就會去先清除掉,這樣就永遠地保證了這個目錄裏面的文件都是最新的。可是也能夠自定義刪除某個目錄,文檔請戳這裏。
const { cleanWebpackPlugin } = require('clean-webpack-plugin') // 先引入這個包,須要使用這種方式
plugins: [
new cleanWebpackPlugin() // 使用,默認不須要進行傳參, 根據實測,在3.X的版本,能夠直接引入
]
複製代碼
若是要使用多個lodaer,只須要將規則rules
屬性下面,放一個數組,裏面能夠有多個對象
module: {
rules: [{ // 關於多個loader配置以下,每一個loader都是一個對象
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},{
test: /\.m?js$/, // 匹配文件的後綴名
exclude: /(node_modules|bower_components)/, // 須要剔除的目錄
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-proposal-object-rest-spread']
}
}
}]
}
複製代碼
提示:其實,每個loader或者插件均可以使用單文件的方式,這樣可讓webpack文件變得不是那麼的龐大,可是會形成項目根目錄文件的變得不少,具體根據本身得項目來進行配置。
在轉換TS文件的時候,須要下載typescript ts-loader
的依賴,安裝好之後,須要在項目根目錄新建一個爲tsconfig.json
的JSON文件,配置以下:
{
"compilerOptions": {
"outDir": "./dist/", // 輸出的文件,若是webpack已經配置了,就不須要了
"noImplicitAny": true,
"module": "es6", // 已什麼模塊的方式引入文件,主要有ES6和commonJS
"target": "es5", // 須要編譯成什麼類型的語法,ES5
"jsx": "react", // 使用jsx語法,
"allowJs": true // 在TS文件種是否存在ES的語法,默認true
},
"include": ['./src/', './'], // 引入的文件目錄,須要編譯的文件
"exclude": /node_modules/ // 剔除不須要編譯的目錄,多個使用(xx|xx)這種方式
}
複製代碼
編譯typescript
webpack的配置以下:
module: {
rules: [{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}]
},
複製代碼
lodash是一個一致性、模塊化、高性能的 JavaScript 實用工具庫,主要用於代碼類型約束。在TS裏面使用types/lodash
能夠對TS進行類型約束。**提示:**lodash具備針對性,若是須要對jquery進行類型約束,則須要下載對應的lodash依賴包。
在圖片打包之前,須要下載一個loader,使用file-loader
能夠對圖片進行打包,webpack經常使用配置以下:
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'file-loader',
options: {
name: '[path][name].[ext]' // 自定義名字,[name]名字[ext]擴展名,還能夠加混淆好比哈希值
outputPath: 'images/' //將打包的文件,生成打包相對文件(dist)的images/的目錄下
}
}]
}]
}
複製代碼
說明:圖片打包,默認文件名使用哈希進行混淆,也能夠自定義配置。具體查看webpack官方的url-loader
說明,示例上僅僅只是顯示了一部分。
若是圖片須要進行BASE64的打包,須要下載url-loader
的一個loader,可是須要注意的是,file-loade
和url-loader
的處理是同樣的,惟一不同的就是url-loader
要比file-loade
的功能更增強大,使用的方法和file-loade
的方法如出一轍,並無什麼區別,可是url-loade
擁有更多的配置項。
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loade',
options: {
name: '[path][name].[ext]', // 自定義名字,[name]名字[ext]擴展名,還能夠加混淆好比哈希值
outputPath: 'images/', //將打包的文件,生成打包相對文件(dist)的images/的目錄下
limit: '1024', // 圖片打包base的大小限制,單位是字節
}
}]
}]
}
複製代碼
使用url-loader
會默認的將圖片打包成了base64的文件,可是在正常狀況下,只有在圖片比較小的話,纔會打成base的格式,所以須要在options
裏面進行圖片大小進行配置
在打包css的時候,須要下載一個css-loader
和style-loader
lodaer去作編譯,若是要使用預編譯,則須要安裝對應的預編譯loader。例如:sass須要 sass-loader
和node-sass
這兩個loader,根據實驗,只須要sass-loader
就能夠了。
css-loader
用來打包css
style-loader
用來掛在頁面,將這個loader自動掛在到html頁面上,通常方式在html頭部
基本配置信息以下(包含了sass預處理器):
module.exports = {
module: {
rules: [{
test: /\.css$/, // /\.sass$/
use: [ 'style-loader', 'css-loader' , 'sass-loader']
}]
}
}
複製代碼
給CSS3添加前綴須要使用postcss-loader
lodaer和 autoprefixer
插件,繼續使用上面的例子,基本配置以下:
module.exports = {
module: {
rules: [{
test: /\.css$/, // /\.sass$/
use: [ 'style-loader', 'css-loader' , 'sass-loader','postcss-loader'] // 寫法1
use: [ 'style-loader', 'css-loader' ,'sass-loader',{ // 寫法2,能夠對每一個lodaer作單獨配置
loader:'postcss-loader',
options: {
plugins: [
require("autoprefixer") /* 生成瀏覽器前綴 */
]}
}]
}]
}
}
複製代碼
若是要讓它自動添加前綴的話,須要在項目根目錄新建一個文件(也能夠是其它文件夾,全局配置通常都放在根目錄),postcss.config.js
,在裏面進行一個配置,也能夠如上代碼那樣,寫在webpack.config.js
中;基本配置信息以下:
module.exports = {
plugins: [ //插件的方式
require('autoprefixer') // 加載模塊 默認寫法
require('autoprefixer')({ // webpack或者postcss.config.js配置,
overrideBrowserList: 'last 100 versions'
})
]
}
複製代碼
autoprefixer
在默認的配置下,只能自動的添加webkit
的前綴信息,若是須要添加更多的配置,還須要添加額外的參數。須要在
package.json
裏面添加一個屬性,屬性名是browserslist
,對應的是一個數組,裏面填入瀏覽器、或者node版本的名稱,例如:"last 100 versions"
;若是須要在
webpack
裏面配置的話,就須要使用overrideBrowserList
屬性去替換browserslist
這個屬性,不然在編譯的時候,webpack
會有錯誤提示。關於browserslist
的具體用法,請點擊這裏
CSS模塊化機制,簡單配置:
module.exports = {
module: {
rules: [{
test: /\.css$/, // /\.sass$/ // 匹配的後綴名
use: [ 'style-loader', { // 配置須要的加載器,loader
loader: 'css-loader',
options: {
modules: {
localIdentNane: '[name]_[hash:base64:10]' // 自定義class的名字,bese須要截取
}
}
}, 'sass-loader']
}]
}
}
複製代碼
若是開啓了模塊化操做,那麼在模塊化導入的時候,文件就只能是局部的方式導入,不然webpack在編譯的時候,會出錯,例子以下:
import 'xxx.css' // 全局引入
import xxx from 'xxx.ss' // 局部引入
複製代碼
打包字體:打包字體和打包文件同樣,loader用的也是打包圖片的那個file-loader
module: {
rules: [{
test: /\.(woff|woff2|svg|ttf|eot )$/, // 字體文件後綴名
use: [{
loader: 'file-loader',
options: {
outputPath: 'font/' //生成的文件夾,將打包的文件,放在裏面
name: [name].[ext] // 修改輸出文件名,這樣就默認原來的文件名和後綴名
}
}]
}]
}
複製代碼
webpack-dev-server 可以用於快速開發應用程序,因此簡稱devServer;devServer是用來提升開發效率的,不是用devServer來作打包,它提供了一些配置項,能夠用於改變devServer的默認行爲,要配置devServer,除了能夠在配置文件裏經過devServer傳入參數,還能夠經過命令行傳入參數。
/* 截取的vue cli的例子 經過命令傳遞的參數*/
"dev": "webpack-dev-server --host 0.0.0.0 --inline --progress --config build/webpack.dev.conf.js",
複製代碼
可是須要注意的是:devServer 只適用於開發模式
webpack開啓本地服務器安裝一個內置插件webpack-dev-server
來幫咱們開啓一個本地服務,雖然webpackDevServer
插件是內置的,可是依然須要下載,只是不須要引入,須要在webpack.config.js
和package.json
文件進行配置,配置內容以下:
/* webpack.config.js 配置 */
module.exports = {
devServer: {
contentBase: './dist' // 配置打包的路徑
open: true, // 設置是否默認打開
prot: "8080", // 端口
hot: true , // 開啓熱更新
}
}
/* package.json 配置 */
"scripts": {
"dev": "webpack-dev-server --open"
}
複製代碼
在正確配置了webpack-dev-server
之後,從dist
目錄中提供文件,默認地址是:localhost:8080
,也能夠自定義配置,配置方案如上代碼。更多配置點擊這裏,可是這種方法,會更新全部數據,能夠理解成是"頁面刷新"
webpack-dev-server在編譯後不會寫任何輸出文件。相反,它將捆綁文件保存在內存中併爲它們提供服務,就好像它們是安裝在服務器根路徑上的真實文件同樣。若是您的頁面但願在不一樣的路徑中找到捆綁包文件,則可使用
publicPath
dev服務器配置中的選項更改此選項。
在使用webpack熱更新的時候,須要有一個插件HotModuleReplacementPlugin
,簡稱是HMR,這個插件是webpack集成的一個內置插件,在使用的時候,不須要下載,可是要導入webpack
。
可是HotModuleReplacementPlugin
這個插件不能用於生產模式,熱更新也是devServer裏面的一個小項。 HotModuleReplacementPlugin
裏面的配置項,能夠忽略,官方說是實驗性的,不推薦配置。
const webpack = require('webpack')
plugins:[
new webpack.HotModuleReplacementPlugin({
multiStep: true, // 將分兩步構建 - 首先編譯熱更新塊,而後編譯剩餘的普通資產
fullBuildTimeout: Number // 時間,表示啓用 multiStep 這個之間的延遲
requestTimeout: Number // 時間(毫秒) 用於下載清單的超時時間
});
]
複製代碼
請注意,
webpack.HotModuleReplacementPlugin
徹底啓用HMR是必需的。若是webpack
或者webpack-dev-server
使用該--hot
選項啓動,則會自動添加此插件,所以您可能不須要將此添加到您的webpack.config.js
。
"dev": "webpack-dev-server --host 0.0.0.0 " // 上述說明的實例,不須要webpack.config.js配置
複製代碼
dev-server 使用了很是強大的 http-proxy-middleware 包。更多高級用法,請查閱其文檔;在咱們作開發的時候,會由於跨域問題致使沒法進行數據請求,所以須要藉助wenpack
提供的反向代理,既porxy
,使用方法以下:
/* 省略其它代碼 */
devServer: {
porxy: {
"/api": "http://localhost:3000", // 基礎用法,將/api綁定到目標服務器。
"/api": { // 採用配置的用法,用法二
target: "http://localhost:3000", // 目標服務器
pathRewrite: {"^/api" : ""}, //路徑重寫,這樣在前端訪問的時候,就不須要傳/api
secure: false, // 配置是否須要使用https的方式,默認是不容許
}
}, // 多個API請求同一服務器的寫法
porxy:[{
context: ["/auth", "/api"], // 多個請求
target: "http://localhost:3000", // 目標服務器
}]
}
/*** 前端請求,已axions爲例 ***/
axios.get('/api/xxx').then(red => { xxx })
axios.get('// xxx').then(red => { xxx }) // 配置請求的方式訪問 忽略掉/api
複製代碼
假設有多個API
請求都在同一個服務器,可使用context
上下文的方式跟上一個數組,代碼如上例子,關於webpack proxy
的更多配置,請戳這裏訪問官網更多說明。
webpack 預加載
其實配置devtool就是在配置SourceMap,意爲:源文件映射,可以快速找到代碼出錯的位置,可是這種方式,須要打包完了之後才能看到是否出錯;可是也有折中的解決方案,須要在package.json
裏面設置一個腳本,能夠自動的爲咱們打包,但它是一個文件協議,正常來講,頁面須要手動刷新,全部仍是使用devServer
的方式會比較好點兒。
module.export = {
/* cheap-module-eval-source-map 開發環境使用,速度快,包含三方模塊 僅提示行錯誤*/
/* cheap-module-source-map 生產環境使用, 其實也能夠不使用*/
/* source-map 源文件映射 inline-source-map(精準告訴你哪行那列出錯)*/
devtool: 'cheap-module-eval-source-map'
}
/*================================= package.json ===============================*/
"scripts": {
"dev": "webpack --watch"
}
複製代碼
devtool
您可使用SourceMapDevToolPlugin
, 而不是使用該選項,EvalSourceMapDevToolPlugin
由於它有更多選項。切勿同時使用devtool
選項和插件,該devtool
選項在內部添加插件,所以您最終會將插件應用兩次。
devtool
您可使用SourceMapDevToolPlugin
, 而不是使用該選項,EvalSourceMapDevToolPlugin
由於它有更多選項其實這句話,我也不太理解是什麼意思? 若是須要更加細粒度的控制,就使用SourceMapDevToolPlugin
這個插件,可是不能同時使用,緣由上面也說了。 其實就我我的以爲,自帶的就夠了。
Tree Shaking翻譯過來就是搖晃樹枝 ,因此簡稱搖樹;舉個簡單的例子:秋天的馬路,馬路兩邊種了不少行道樹,有的葉子枯黃、有的葉子任然是綠色,由於枯黃的葉子隨風飄落,爲了更好的解決落葉的問題,就找了一個大型的器械,抓着樹幹使勁搖晃,枯黃的葉子也就掉落了下來,剩下的就是不易掉落的綠色葉子。
可是反過來能夠這樣理解,就是說,對於webpack
來講,入口就至關因而一棵樹幹,入口上面有不少模塊,這些模塊就是樹枝,可是這些依賴模塊並無所有使用,或者只使用了模塊中的某一個功能,這時就須要藉助Tree Shaking
它將不須要的模塊給搖掉,也就是說:在打包後文件裏面,代碼都是精簡且須要的。原理請戳這裏:Tree-Shaking性能優化實踐 - 原理篇。
tree shaking 是一個術語,一般用於描述移除 JavaScript 上下文中的未引用代碼(dead-code)。它依賴於 ES2015 模塊系統中的靜態結構特性,例如
import
和export
。這個術語和概念其實是興起於 ES2015 模塊打包工具 rollup。新的 webpack 4 正式版本,擴展了這個檢測能力,經過
package.json
的"sideEffects"
屬性做爲標記,向 compiler 提供提示,代表項目中的哪些文件是 "pure(純的 ES2015 模塊)",由此能夠安全地刪除文件中未使用的部分。
說了這麼多? 那在webpack裏面應該怎樣使用呢?須要在package.json
中配置
{
"sideEffects": false, // 簡單版本,
"sideEffects": [ // 使用數組的方式,我的理解:就是將不須要搖的東西給剔除出來,。
"@babel/polyfill",
"./src/some-side-effectful-file.js",
"*.css"
]
}
複製代碼
這樣只是標記「未使用代碼(dead code)」,可是須要是在編譯後(bulid)刪除,所以:咱們須要切換到生產模式(production)來表示,命令模式(--optimize-minimize
);使用配置的方式,代碼以下:
mode: 'production', // 必須是生產模式
optimization: { // 設置刪除爲標記的 未使用代碼,也就是死代碼
usedExports: true
}
複製代碼
總結:Tree Shaking只在生產模式有效,開發模式無效,而且只能使用ESmodul的方式,詳細說明請戳這裏。
在vue cli 2.x的版本里面有不少webpack配置,一開始我也不知道爲何須要這麼配置,經過後來的瞭解才知道,在webpack
裏面有不少模式,好比:生產模式、開發模式,介於它們之間的還有各類配置文件、公共模塊等,如下是vue cli的webpack
配置目錄。
.
|—— vue cli
|—— config
| |—— dev.env.js
| |—— index.js
| |—— prod.env.js
| |__ test.env.js
|—— build
| |—— build.js
| |—— check-versions.js
| |—— utils.js
| |—— vue-loader.conf.js
| |—— webpack.base.conf.js
| |—— webpack.dev.conf.js
| |__ webpack.prod.conf.js
|
.
複製代碼
但是有這麼多的單獨的文件,最終須要怎麼才能合併在一塊兒呢? 是直接引入仍是須要使用插件呢?這裏須要使用一個插件,這個插件的名字是:webpack-merge
,在使用它的時候,須要先去安裝這個插件。
若是將上面的目錄進行一個拆分,假設就只有webpack.prod.conf.js
、webpack.dev.conf.js
和webpack.base.conf.js
這麼三個文件,其中webpack.base.conf.js
是一個公共文件,另外兩個表示生產模式和開發模式。使用webpack-merge
的方法以下:
/* ======= 以生產模式爲例 webpack.prod.conf.js======= */
const merge = require('webpack-merge');
const common = require('./webpack.prod.conf.js');
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map'
});
複製代碼
還須要在npm
裏面進行配置,仍然已vue cli目錄爲例,在package.json
中加入如下內容:
scripts": {
"dev": "webpack-dev-server --open --progress --config build/webpack.dev.conf.js",
"build": "webpack --config build/webpack.prod.conf.js"
}
/* --progress 顯示進度條的意思 */
複製代碼
就只想使用一個文件入口,在裏面配置一個環境變量,而後就能按照本身的須要,產生不一樣的編譯結果,實施方法能夠按照以下操做。
那裏面的commonConfig
文件和prodConfig
還有這個devConfig
它們也是一個單獨的文件,爲了不一個文件很大,因此在使用的過程當中,仍是單獨分開寫的比較好,只不過在具體配置的時候,使用一個環境變量來判斷。
module.export = (env) => {
if(env && env.production){ // 條件判斷
return merge(commonConfig, prodConfig); // 生產模式(線上模式)
} else {
return merge(commonConfig, devConfig); // 開發模式
}
}
複製代碼
看了上面的代碼,會想到一個問題,條件判斷的變量env && env.production
是從哪裏來的,其實這個變量是從package.json``裏面配置得來的,也就是說:若是須要使用這種方式的話,就須要去更改啓動腳本,代碼以下:
scripts": {
"dev": "webpack-dev-server --open --progress --config build/webpack.base.conf.js",
"build": "webpack --env.production. --config build/webpack.base.conf.js"
}
/* --progress 顯示進度條的意思 */
複製代碼
能夠很清除的看到dev
和build
這兩個方法啓動的目錄文件都是同一個,可是在build
裏面多了一個env.production
這個屬性,其實,這個變量就是上面的條件判斷語句所須要的參數。
環境變量還能夠這樣使用,就nodeJS
提供的process.env.NODE_ENV
,具體的時候方法,參考簡書NodeJs/Vue項目中對process.env的使用。
在不少時候,咱們都須要使用eslint來幫助咱們進行代碼檢查和規範,這樣每每在團隊中,能作到風格統一,很是有利於團隊協做、後期維護等,但配置eslint是很是繁瑣的,下面一塊兒來看看,咱們如何在webpack
中如何配置eslint
吧?在慕課手記中也有關於自定義的詳細說明,更多查看請戳這裏。
eslint
在使用前,須要先安裝eslint
這個包,更多安裝方法戳這裏查看官方教程,安裝方法以下:
npm install eslint --save-dev // 下載eslint這個安裝包
npx eslint --init // 運行這個命令進行eslint的詳細配置
複製代碼
關於eslint
配置說明,當運行npx eslint --init
的時候,會彈出以下信息:
? How would you like to use ESLint? (Use arrow keys) //如何配置eslint這個文件,你想如何使用
To check syntax only // 僅檢查語法
> To check syntax and find problems // 檢查語法並找出問題
To check syntax, find problems, and enforce code style //檢查語法、發現問題和強制代碼樣式
/* 我選擇的是檢查語法並找出問題,而後就有了下面的配置信息 */
? What type of modules does your project use? // 你想使用什麼類型的模塊呢?
JavaScript modules (import/export) // 基於ES6
> CommonJS (require/exports) // 這個主要是node中使用
None of these // 這些都不是
/* 由於在個人實驗中,用的是vue,所需須要使用esmodule這種語法,而後彈出的信息以下 */
? Which framework does your project use? (Use arrow keys) // 你想使用那個框架
React
> Vue.js // 由於我是vue,全部選擇vue
None of these // 其它框架
/* 當選擇vue後,配置如以下,問你是在那個地方運行,能夠多選,使用空格點亮,而後回車 */
? Where does your code run? (Press <space> to select, <a> to toggle all, <i> to invert selection)
>(*) Browser // 瀏覽器
( ) Node // node
/* 當我選擇之後,會出現以下配置 固然是使用JS文件的方式,我的愛好*/
? What format do you want your config file to be in? (Use arrow keys) // 使用什麼文件做爲配置文件
> JavaScript
YAML
JSON
/* 問你是否想安裝它們,這裏固然選擇是了 */
? Would you like to install them now with npm? (Y/n) // y 基礎配置過程就完畢了
複製代碼
當一些列配置完畢後,會發如今項目的根目錄中有一個.eslintrc.js
的配置文件,這個文件就是eslint
的配置文件啦,更多配置請戳這裏,也能夠選擇第三方公司的編碼配置,安裝方法參考eslint配置(使用Airbnb編碼規則),比較變態的就是airbnb
規則了,很是的嚴格。
雖然這樣在vscode
(前提是webpack
中有插件)中可使用了,可是對於其它的代碼編輯器,卻不會怎麼報錯? 因此還須要下載一個eslint-loader
才能夠,具體操做方法以下:
npm install eslint-loader --save-dev
複製代碼
下載好了之後,基本配置以下,可是必定要將eslint-loader
放在最後面,由於loader
的執行順序是從後往前:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader", "eslint-loader"]
}
]
}
};
複製代碼
僅僅是這樣(若是不作以下配置,只能在cmd
控制檯顯示),仍是不行滴,還須要一點兒額外的其它配置,配置以下:
module.exports = {
devServer: {
overlay: true // 在瀏覽器上彈出一個層,也就是在瀏覽器中顯示全屏覆蓋
}
};
複製代碼
但都知道在vue cli
2 的版本中,當檢測到警告信息,會輸出在瀏覽器的控制檯顯示,可是這個問題,我還木有解決,有知道的小夥伴,能夠告訴我如下。
overlay:{
warnings: false,
errors: true
}
複製代碼
我也按照vue cli
源代碼進行了一個配置,發現並無按照個人意願來。
在剛學Vue.js
的時候,那時候運用的不是很熟,有時候須要操做DOM,可是Vue.js
操做DOM很是的不方便;有時候須要獲取到 一個列表裏面全部的標籤,那時候就想到了使用Jquery
來幫我操做DOM,當時就覺得像其它JS
文件同樣全局導入就能夠了,可在實際運用的時候卻傻眼了,就發現,可以在控制檯輸出Jquery
對象,可是卻沒法操做DOM
,這讓我很抓狂。
通過學習,知道webpakc
自己就已經提供了一套關於shimming
解決方案:使用webpack
內置的ProvidePlugin
插件和expose-loader
,在網上找了不少文檔,在使用webpack
內置的ProvidePlugin
插件的時候,雖然勉強解決這個問題,可是仍是有一些小問題,就eslint報錯的問題。後來發現使用expose-loader
的方式也能夠解決這個問題。
ProvidePlugin
是webpack
內置插件,所以在使用前須要導入webpack
,它主要的功能是:自動加載模塊,而沒必要處處 import
或 require
, 這也是webpack
推薦的使用方法。
可是:對於 ES2015 模塊的 default export,你必須指定模塊的 default 屬性,由於它的名字;以
jquery
爲例: 它實際上就是import $ from 'jquery'
,具體例子請看以下代碼。更多例子請戳這裏,查看官方示例說明。
const webpack = require('webpack')
/* 省略其它代碼 */
plugins: [
new webpack.ProvidePlugin({
$: 'jquery', // 後面的jquery其實就是 import $ from 'jquery'
JQuery: 'jquery'
})
]
複製代碼
能夠經過expose-loader
向webpack
注入一個全局的公共模塊,假設用了這個方法導入了jquery
的話,是能夠全局使用,能夠理解成綁定到了window
上,所以,在使用它的時候,須要下載這個expose-loader
,以jquery
爲例,使用方法以下:
module: {
rules: [{
test: require.resolve('jquery'), // 導入jquery模塊,但這個方法是node.js提供,和webpack無關
use: [{
loader: 'expose-loader',
options: 'jQuery' // 全局使用的名稱, window.jQuery
},{
loader: 'expose-loader',
options: '$' // 全局使用名稱, window.$
}]
}]
}
複製代碼
可是這種方法,須要在局部導入(也就是說,須要每一個頁面都須要導入),而後才能進行全局暴露,可是若是須要全局注入的話,顯然這種方式不太穩當。
webpack
提供了一個Code Splitting
拆分代碼,點擊這裏,能夠查看代碼分離的方式以及介紹。
使用CommonsChunkPlugin
用於避免它們的重複依賴,可是沒法進一步優化;在webpack4
的版本之後,刪除了optimization.splitChunks
這個屬性;SplitChunksPlugin方法使用以下:
module.exports = {
splitChunks: {
chunks: "all", // 同步和異步都作分割
cacheGroups: { // 緩衝組
vendors:false,
default: false
}
}
}
複製代碼
SplitChunksPlugin
的更多配置以下,具體參考官方說明,戳這裏點擊官方文檔。
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async', // async 默認推薦使用,異步加載作分割, initial 同步 all 同步和異步都作分割
minSize: 30000, // 字節 引入的包或者模塊大於這個這個值,纔會作代碼分割,只針對同步加載
maxSize: 0, // 超過 minSize 之後,會進行二次打包,默認不配置,不能強拆
minChunks: 1, // 引入次數,引入次數爲多個,能夠打包
maxAsyncRequests: 5, // 請求超過5個的部分不拆分,通常默認值
maxInitialRequests: 3, // 頁面初始化同時發送的請求數量最大不能3個,超過之後就不會被拆分,默認值就會
automaticNameDelimiter: '~', // 用以代碼分離打包的文件名默認鏈接符,cacheGroups裏面的vendors
automaticNameMaxLength: 30, // 最長字節數,不能超過這個值
name: true, // 拆分的名字, true表示根據模塊名和cacheGroups組的key來自動生成文件名
cacheGroups: { // 緩存配置,一個文件import多個庫,若是須要多個庫打包成一個文件,則使用這個緩存組
vendors: {
test: /[\\/]node_modules[\\/]/, // 檢測引人的庫是不是node_modules下面的
priority: -10, // 權重,決定哪一個組的優先配置
name: "vendors" // 自定義名字,不須要後綴名
},
default: { // 前面沒有匹配上,則使用這個組,一般是業務代碼
minChunks: 2, // 引入超過2次才重新打包成一個新文件
priority: -20, // 權重
reuseExistingChunk: true // 當爲true後就不會重複打包,會進行自動複用。
}
}
}
}
};
複製代碼
在chunks
的時候,還須要走cacheGroups
緩衝組,分離出來的文件名是:cacheGroups
裏面的vendors
,中間的鏈接符是automaticNameDelimiter
,例vendors-main.js
cacheGroups
能夠自定義多個組,若是多個組都知足要求,則以權重大的組爲準。
webpack
爲了更好的提高性能,最好的仍是使用異步的方式,這也是官方推薦。
當涉及到動態代碼拆分時,webpack 提供了兩個相似的技術。對於動態導入,第一種,也是優先選擇的方式是:ES7提出的一個草案,既
import()
語法。第二種,則是使用 webpack 特定的require.ensure
。先來講說第一種:
動態導入最大的好處就是實現了懶加載,用到那個模塊就纔會調用那個模塊,很是適合ASP導入,能夠大大的減小等待時間,但使用這個須要用到babel
去轉,也就是須要下載@babel/plugin-syntax-dynamic-import
這個插件,使用方法以下:
{
"plugins": ["@babel/plugin-syntax-dynamic-import"] // 使用插件,在webpack plugins裏面添加
}
複製代碼
在頁面添加動態import
導入懶加載的方式,這種方式會返回一個promise
對象,代碼以下:
/* 聲明這個方法 須要一個函數 */
function getComponent() {
import(/* webpackChunkName: "lodash" */ 'lodash').then( _ => {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}).catch( error => 'An error occurred while loading the component');
}
/* 調用這個方法 若是不調用則不執行*/
getComponent().then(component => {
document.body.appendChild(component);
})
複製代碼
這種方法,則會對代碼進行分離,將動態打入的第三方模塊,會單獨的打一個文件,而本身所寫的業務代碼,則會被打包到新的一個文件裏面。
/* webpackChunkName: "lodash" */ 'lodash'
魔法字符串,懶加載,配合SplitChunksPlugin
使用,能夠進行一個單獨配置,其實這個配置和SplitChunksPlugin
是共用。
module.exports = {
splitChunks: {
cacheGroups: { // 緩衝組
vendors: {
test: /[\\/]node_modules[\\/]/, // 檢測引人的庫是不是node_modules下面的
priority: -10, // 權重,決定哪一個組的優先配置
name: "vendors" // 自定義名字,不須要後綴名
},
default: false
}
}
}
複製代碼
可是使用懶加載的時候,會有一個弊端,就是當用戶須要一個模塊的時候,只有觸發之後,才能去加載對應的模塊,這就會形成一個網絡的延時,有一個等待期,不利於用戶體驗,因此就須要另一個技術,也就是預加載,當頁面自動加載出來之後,利用閒置的帶寬,去加載其它可能須要的模塊。
這個是webpack 4.6.0
新增的一個功能,用通俗的話來講,就是在網絡空閒的時候,纔去自動下載其它的非必要模塊,這種方式極大的提高了用戶體驗,也解決了等待延時問題,但是要怎麼使用呢?
/* 使用方法和上面的 懶加載是同樣的,只是這個魔法字符串裏面的參數不同 */
import(/* webpackPrefetch: true */ 'LoginModal');
複製代碼
在聲明導入時使用這些內聯指令容許webpack輸出「Resource Hint」,使用方法如上,它告訴瀏覽器:
區別:preload
是和核心代碼一塊兒加載,prefetch
預加載
緩存帶來的代碼提高是有限的,因此使用懶加載代碼優化是如今性能優化的主要使用方式。
關於打包分析,官網爲咱們提供了一個內置插件Bundle Analysis
,在guider
下面的Code Splitting
裏面的Bundle Analysis
,他有幾種類型,webpack-chart:(交互式餅圖)等類型,具體請戳這裏。使用方法也很簡單,只須要在package.json
中配置一段腳本便可,例子以下:
scripts": {
"build": "webpack --profile --json > stats.json --env.production. --config build/webpack.base.conf.js"
}
複製代碼
其實也能夠直接使用webpack --profile --json > stats.json
, 打包完成後,會生成一個stats.json
文件,這個文件就是結果分析,而後須要將這個文件上傳到這個網站,進行數據分析,可是這個表,感受很是不人性化,我的以爲很難看,因此須要使用webpack-bundle-analyzer
插件。
Webpack Bundle Analyzer
也是一個打包分析,它和webpack-chart
不一樣的是,Webpack Bundle Analyzer
是一個很直觀的平面圖,這是一個插件,因此在使用的時候,須要進行下載安裝,npm install --save-dev webpack-bundle-analyzer
。
若是使用了這個之後,在打包的時候,控制檯不會輸出打包信息,好比文件、 打包時間、chunk等信息,這也算是一個弊端。
在使用它的時候,也須要有如上的package.json
中配置(實測,可不須要使用),在webpack
裏面的基本配置以下,更多配置請戳這裏;
// 導入插件
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// 使用它
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
複製代碼
它默認是打包在js
文件裏面,這樣就會致使文件變得很大,因此將CSS
代碼分離出來是頗有必要的,使用CSS
代碼分析則須要使用一個插件來幫咱們完成,這個通常只作線上版本,在開發版本則不須要,這個插件的名字是MiniCssExtractPlugin
,點擊這裏查看更多官方配置。
npm install --save-dev mini-css-extract-plugin // 須要先安裝
複製代碼
簡單的配置說明,在使用的時候須要將style-loader
替換爲MiniCssExtractPlugin.loader
,若是須要在開發環境中使用熱更新,須要從新進行一個設置。
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 導入插件
module.exports = {
plugins: [
new MiniCssExtractPlugin({ // 方法同output裏面的方法,最好就是加一個hash值,防止緩存
filename: '[name].css', // 生成的文件名
chunkFilename: '[id].css', // 構建時生成,主要是防止文件更新瀏覽器不更新,緩存致使的
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader, // 替換style-loader
options: { // 其它的配置項
publicPath: '../', // 指定的地址,同等與output裏面的publicPath
hmr: process.env.NODE_ENV === 'development', // 環境變量
},
},
'css-loader',
],
},
],
},
};
複製代碼
CSS代碼分離,默認是不會被壓縮,若是想要代碼壓縮,則須要使用optimize-css-assets-webpack-plugin
插件,但須要注意的是:設置optimization.minimizer
會覆蓋webpack提供的默認值,所以須要指定,JS minimalizer, 使用方法以下:
const TerserJSPlugin = require('terser-webpack-plugin'); // 不添加則JS不會被壓縮
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 導入CSS分離插件
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); // CSS代碼壓縮
module.exports = {
optimization: { // 添加一個屬性,
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
複製代碼
設置optimization.minimizer
會致使重寫,因此須要下載terser-webpack-plugin
這個插件,去壓縮JS
,若是沒有這個插件就會致使,CSS
代碼被壓縮了,可是JS
代碼則不會被壓縮。
Webpack 在啓動後會從配置的入口模塊出發找出全部依賴的模塊,Resolve 配置 Webpack 如何尋找模塊所對應的文件。 Webpack 內置 JavaScript 模塊化語法解析功能,默認會採用模塊化標準里約定好的規則去尋找,但你也能夠根據本身的須要修改默認的規則。
關於resolve
的基本配置以下,更多配置戳這裏查看官方教程。
const path = require('path') // node提供的文件路徑模塊
module.exports = {
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.json'], // 自動解析肯定的擴展,能夠省略的擴展名
alias: { //建立 import 或 require 的別名,來確保模塊引入變得更簡單。
"@": path.resolve(__dirname, '../src'),
xyz$: path.resolve(__dirname, 'XXX.js') // 精確匹配 xyz
}
}
};
複製代碼
在搭建vue
腳手架以前,須要下載兩個loader
,分別是:vue-loader
和 vue-template-compiler
,具體的安裝方法查看Vue loader官方說明。
npm install -D vue-loader vue-template-compiler // 安裝
複製代碼
須要注意的問題:每一個
vue
包的新版本發佈時,一個相應版本的vue-template-compiler
也會隨之發佈。編譯器的版本必須和基本的vue
包保持同步,這樣vue-loader
就會生成兼容運行時的代碼。這意味着你每次升級項目中的 vue 包時,也應該匹配升級 vue-template-compiler。
在main.js
中加入最基本的代碼,這也是最基本的入口配置信息
import Vue from 'vue'
window.vm = new Vue({
el: '#app',
render: h => h(App),
components: { App },
template: '<App/>'
})
複製代碼
正常來講,webpack
在編譯的時候,是不認識.vue
的後綴名,所以須要咱們手動的在webpack
裏面新增一個loader
,用於識別.vue
文件,基本配置以下:
// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
// 它會應用到普通的 `.js` 文件
// 以及 `.vue` 文件中的 `<script>` 塊
{
test: /\.js$/,
loader: 'babel-loader'
},
// 它會應用到普通的 `.css` 文件
// 以及 `.vue` 文件中的 `<style>` 塊
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
}
]
},
plugins: [
// 請確保引入這個插件來施展魔法
new VueLoaderPlugin()
]
}
複製代碼
vue loader15+
的版本都須要去使用一個vue-loader/lib/plugin
插件,這個插件不用單獨下載,在使用vue-loader
的時候,這個插件就已經有了。
爲了更快的使用打包優化,須要及時更新nodeJS
以及webpack
的版本,儘量的減小一些loader
的轉換,而且須要剔除一些沒必要要的目錄,好比:node-modules
的文件夾,插件儘量得時候使用官方推薦。 還可使用webpack
內置的DllPlugin
插件去幫咱們進行打包速度優化。
DllPlugin
插件專門用於單獨的webpack配置中,以建立僅限dll
的捆綁包。它建立了一個manifest.json
文件,用於DllReferencePlugin
映射依賴項(先建立一個,而後進行復制,這樣就提高了打包效率)。
更多的方法戳這裏查看官方教程,一般是建立一個webpack.dll.js
文件,用來專門配置dllplugin
,目的是爲了將一些公共的庫,打包成一個文件,後續打包不會從新打包,只會去引用打包好的包。
const path = require('path') // 導入node 模塊
module.exports = {
mode: 'production', // 生產模式
entry: {
vendors: ['vue','jquery'] // 入口文件,自定義屬性
},
output:{
filename: '[name].dll.js', // 輸出,多個文件打包成一個文件
path: path.resolve(__dirname, '../dll'), // 打包的文件夾目錄
library: '[name]' // 導出全局變量,用於其它文件
}
}
複製代碼
可是這種方法,不會自動添加到html
頁面中,所以須要一個插件add-asset-html-webpack-plugin
,來幫我咱們將webpack.dll.js
打包後文件自動添加到html
中,關於更多說明戳這裏查看NPM
教程
cnpm i add-asset-html-webpack-plugin -D // 安裝
複製代碼
使用它的時候,此時就不能寫在webpack.dll.js
文件中,應該寫在公共的文件當中,好比webpack.base.conf.js
文件裏面,基本配置方法以下:
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 導入自動生成html插件
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin'); // 自動添加插件
const webpackConfig = {
entry: 'index.js',
output: {
path: 'dist',
filename: 'index_bundle.js',
},
plugins: [
new HtmlWebpackPlugin(),// 更多說明請看前面的 HtmlWebpackPlugin 配置
// require.resolve和 path.resolve, 在這裏的用法是同樣的,
new AddAssetHtmlPlugin({ filepath: require.resolve('../dll/vendors.dll.js') }),
],
};
複製代碼