如下是我學習webpack
過程當中遇到的問題以及記錄。
基本配置可參見官方配置javascript
mode
環境的定義生產環境:production
開發環境:development
不定義環境:none
css
entry
入口文件"path/to/entry.js"
,等價於{main:"path/to/entry.js"}
。配合路由插件實現多頁面。{a:"path/to/entryA.js",b:"path/to/entryB.js"}
這裏的"path/to/entry.js"
,必須使用絕對路徑,相對路徑會打包報錯,找不到文件。能夠利用node.js
的path
模塊來自動生成絕對路徑。(不須要單獨安裝path
庫)。代碼以下:html
const path = require("path"); config = { // 這裏的 __dirname 是node.js的全局變量,指的是當前js文件所在絕對路徑 entry: path.resolve(__dirname, "path/to/entry.js") };
多入口若是這樣寫["path/to/entryA.js","path/to/entryB.js"]
,會致使打包的 js 只有一個main.js
,邏輯全都掛載在頁面A
,頁面B
是空白的。因此不建議這樣寫。
output
打包輸出配置經常使用的幾個配置選項以下:java
path
:指的是打包文件輸出的根目錄,必須使用絕對路徑。filename
:打包後的js
文件名。例如"js/[name].[hash:8].bundle.js"
,這裏的[name]
指的是入口entry
中定義的main
a
b
。publicPath
:是生成的js
,css
,images
等靜態資源的引用路徑的基本路徑。例如/assets/
,那麼在打包生成的html
文件中引入的js
,css
,images
等靜態資源的路徑的前面會所有自帶/assets/
。還可使用例如https://cdn.example.com/
這樣的 cdn 配置,這樣能夠更好的處理生產環境使用 cdn 靜態資源的狀況。通常不作這項配置也可。module
處理靜態資源的規則詳細可參見官方配置node
處理圖片文件webpack
須要安裝模塊file-loader
,url-loader
。git
具體配置以及說明可參見以下代碼:github
{ test: /\.(png|svg|jpg|gif|jpeg|tif)$/, use: [ // { // webpack經過file-loader處理資源文件,它會將rules規則命中的資源文件按照配置的信息(路徑,名稱等)輸出到指定目錄, // 並返回其資源定位地址(輸出路徑,用於生產環境的publicPath路徑),默認的輸出名是以原文件內容計算的MD5 Hash命名的 // loader: "file-loader", // options: { // outputPath: "images/" // } // }, { // 構建工具經過url-loader來優化項目中對於資源的引用路徑,並設定大小限制,當資源的體積小於limit時將其直接進行Base64轉換後嵌入引用文件,體積大於limit時可經過fallback參數指定的loader進行處理。 // 打包後能夠看到小於8k的資源被直接內嵌進了CSS文件而沒有生成獨立的資源文件 loader: "url-loader", options: { limit: 8129, //小於limit限制的圖片將轉爲base64嵌入引用位置 fallback: "file-loader", //大於limit限制的將轉交給指定的loader處理,開啓這裏後就無需再單獨配置file-loader options會直接傳給fallback指定的loader name: "[name].[ext]", outputPath: "images", //這裏是打包後圖片所在的位置 //這裏的publicPath做用和output配置中的相同,會覆蓋output中的配置項。 //爲了防止css中引入圖片路徑的問題,能夠在這裏判斷若是是開發環境熱更新啓動模式,改爲用根目錄的路徑 /images publicPath: "./images" } } ] }
處理字體文件web
和圖片文件的處理同樣,須要安裝file-loader
模塊。npm
具體配置可參見以下代碼:
{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ { loader: "file-loader", options: { outputPath: "css/fonts", publicPath: "fonts", name: "[name].[hash:8].[ext]" } } ] }
處理css
樣式文件
css
不分離的話,就是樣式<style></style>
都在html
文件的的head
標籤裏面。須要安裝style-loader
模塊。
若是css
分離,則能夠異步同時加載html
文件和css
文件,能夠有效提升加載速度。須要安裝mini-css-extract-plugin
模塊(extract-text-webpack-plugin
模塊不支持webpack4
以上的版本)。
另外還須要安裝css-loader
模塊。
postcss-loader
模塊的做用後面會講到。
具體配置以及說明可參見以下代碼:
const miniCssExtractPlugin = require("mini-css-extract-plugin"); { test: /\.css$/, include: [path.resolve(__dirname, "src")], // 限制打包範圍,提升打包速度 exclude: /node_modules/, // 排除node_modules文件夾 use: [ // { // 當配置MinCssExtractPlugin.loader後,此項就無需配置,緣由看各自做用 // loader: "style-loader" // 將處理結束的css代碼存儲在js中,運行時嵌入`<style>`後掛載到html頁面上 // }, { // 將處理後的CSS代碼提取爲獨立的CSS文件,能夠只在生產環境中配置,但我喜歡保持開發環境與生產環境儘可能一致 loader: miniCssExtractPlugin.loader }, { // CSS加載器,使webpack能夠識別css文件 loader: "css-loader" }, { //承載autoprefixer功能,爲css添加前綴 loader: "postcss-loader" } ] }
處理scss
樣式文件
須要安裝的模塊同上面css
同樣。另外還須要安裝node-sass
和sass-loader
模塊。
postcss-loader
模塊這裏須要安裝postcss-scss
插件來識別處理scss
文件。
具體配置以及說明可參見以下代碼:
{ test: /\.scss$/, include: [path.resolve(__dirname, "src")], // 限制打包範圍,提升打包速度 exclude: /node_modules/, // 排除node_modules文件夾 use: [ // { // 當配置MinCssExtractPlugin.loader後,此項就無需配置,緣由看各自做用 // loader: "style-loader" // 將處理結束的css代碼存儲在js中,運行時嵌入`<style>`後掛載到html頁面上 // }, { // 將處理後的CSS代碼提取爲獨立的CSS文件,能夠只在生產環境中配置,但我喜歡保持開發環境與生產環境儘可能一致 loader: miniCssExtractPlugin.loader }, { // CSS加載器,使webpack能夠識別css文件 loader: "css-loader" }, { //承載autoprefixer功能,爲css添加前綴 loader: "postcss-loader", options: { parser: "postcss-scss" } }, { // 編譯sass,webpack默認使用node-sass進行編譯,因此須要同時安裝 sass-loader 和 node-sass loader: "sass-loader" } ] }
處理less
樣式文件
須要安裝的模塊同上面css
同樣。另外還須要安裝less
和less-loader
模塊。
postcss-loader
模塊這裏須要安裝postcss-less
插件來識別處理less
文件。
具體配置以及說明可參見以下代碼:
{ test: /\.less$/, include: [path.resolve(__dirname, "src")], // 限制打包範圍,提升打包速度 exclude: /node_modules/, // 排除node_modules文件夾 use: [ // { // 當配置MinCssExtractPlugin.loader後,此項就無需配置,緣由看各自做用 // loader: "style-loader" // 將處理結束的css代碼存儲在js中,運行時嵌入`<style>`後掛載到html頁面上 // }, { // 將處理後的CSS代碼提取爲獨立的CSS文件,能夠只在生產環境中配置,但我喜歡保持開發環境與生產環境儘可能一致 loader: miniCssExtractPlugin.loader }, { // CSS加載器,使webpack能夠識別css文件 loader: "css-loader", options: { // 不處理引入圖片的路徑問題 url: false, importLoaders: 1 } }, { //承載autoprefixer功能,爲css添加前綴 瀏覽器css前綴 loader: "postcss-loader", options: { parser: "postcss-less" } }, { // 編譯less,webpack默認使用less進行編譯,因此須要同時安裝 less-loader 和 less loader: "less-loader" } ] }
處理csv|tsv
文件
須要安裝csv-loader
模塊來識別這些文件。
{ test: /\.(csv|tsv)$/, use: ["csv-loader"] }
處理xml
文件
須要安裝xml-loader
模塊來識別這些文件。
{ test: /\.xml$/, use: ["xml-loader"] }
postcss-loader
模塊
PostCSS 是一個容許使用 JS 插件轉換樣式的工具。 這些插件能夠檢查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 編譯還沒有被瀏覽器普遍支持的先進的 CSS 語法,內聯圖片,以及其它不少優秀的功能。
postcss
有許多插件,插件以及配置信息,具體可參見官方說明。
配置文件默認是postcss.config.js
。
處理.sass
須要安裝postcss-sass
轉換器。處理.scss
文件須要安裝postcss-scss
轉換器。處理.less
文件須要安裝postcss-less
轉換器。
在這裏我用了兩個插件autoprefixer
和precss
。
autoprefixer
自動添加各個瀏覽器css
前綴,須要package.json
文件中配置支持的瀏覽器列表browserslist
,才能正確加上所配置瀏覽器的前綴。具體可查看官方說明。
precss
是讓你能夠在css
文件中使用像scss
文件中的變量以及鏈接符。具體可查看官方說明。
或許cssnano
插件一些人會用,這個是壓縮css
的。我這裏壓縮css
用的另外的插件,沒有用postcss
,後面會講到。
plugins
插件配置html-webpack-plugin
這是生成html
文件的插件,會把打包生成的css
文件以及js
文件自動插入到生成的html
文件中。具體可參見官方說明。
能夠動態生成,適用於多入口。單入口只寫一個就能夠了。具體配置以及說明可參見以下代碼:
const HtmlWebpackPlugin = require("html-webpack-plugin"); new HtmlWebpackPlugin({ // 頁面title 若是使用自定義的摸板,那麼摸板title標籤內容爲<%= htmlWebpackPlugin.options.title %>纔可在生成的html文件中正確替換。 title: "index", // 生成的html的文件名以及位置 可添加上相對於打包輸出的路徑,好比"views/index.html" filename: "index.html", // 所使用的自定義摸板 不寫表示使用官方默認的摸板 // 自定義摸板能夠添加一些cdn公共庫,添加公共庫還能夠用下一小節中的方法 // template: "src/index.html", // 須要插入的js模塊 // main表示入口主文件 // common表示提取的公共模塊,在optimization.splitChunks中定義的 // vendors表示提取的第三方模塊,即npm安裝的模塊,也是在optimization.splitChunks中定義的 // manifest運行時的模塊,在optimization.runtimeChunk中定義的。 chunks: ["main", "common", "vendors", "manifest"], // 頁面圖標 favicon: "src/images/備案圖標.png", // 配置每一個html頁面的favicon // 壓縮選項配置 minify: { // 壓縮HTML文件 removeComments: true, // 移除HTML中的註釋 collapseWhitespace: true // 刪除空白符與換行符 // css js已經壓縮了,這裏再也不配置壓縮 //是否壓縮html裏的js 我這裏使用的optimization.minimizer中配置的插件壓縮 // minifyJS: true, // 壓縮html裏的css 我這裏使用的optimization.minimizer中配置的插件壓縮 // minifyCSS: true // 壓縮內聯css }, // 請求js css資源時,附帶哈希值 這對緩存清除(cache busting)十分有用。 hash: true })
第三方庫的公共引入 暴露全局 不用單獨 import
這裏是引入公共的第三方模塊,並暴露全局變量。使用時不用單獨引入,能夠直接使用暴露的全局變量。
也可使用上一小節中提到的html
摸板中插入cdn
公共庫連接的方法,這樣能夠減小本身服務器的壓力。
具體配置以及說明可參見以下代碼:
const webpack = require("webpack"); // _是暴露的全局變量名稱 "lodash"是引入的公共第三方庫 new webpack.ProvidePlugin({ _: "lodash" })
mini-css-extract-plugin
這個插件在處理css
,scss
,less
文件的時候也有說明,這裏主要是對打包輸出css
文件的配置。具體可參見官方說明。
具體配置以及說明可參見以下代碼:
new miniCssExtractPlugin({ // 打包後的css文件輸出路徑以及名稱 filename: "css/[name].[hash:8].css" })
clean-webpack-plugin
這個插件的做用是每次打包,清理過時文件。具體可參見官方說明。
具體配置以及說明可參見以下代碼:
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); // plugins中簡單的插入這一句便可 new CleanWebpackPlugin()
purifycss-webpack
這個插件的做用是打包過程當中消除無用多餘的css樣式
。須要配合glob
使用。
具體配置以及說明可參見以下代碼:
const glob = require("glob"); const PruifyCSSPlugin = require("purifycss-webpack"); new PruifyCSSPlugin({ // src下全部的html // paths: glob.sync(path.join(__dirname, "src/*.html")) // src下全部的js paths: glob.sync(path.join(__dirname, "./src/**/*.js")) })
optimization
優化打包的配置。具體可參見官方說明。
splitChunks
找到 chunk 中共享的模塊,取出來生成單獨的 chunk。
具體配置以及說明可參見以下代碼:
splitChunks: { chunks: "all", // async表示抽取異步模塊,all表示對全部模塊生效,initial表示對同步模塊生效 cacheGroups: { vendors: { // 抽離第三方插件 test: /[\\/]node_modules[\\/]/, // 指定是node_modules下的第三方包 // 打包後的模塊文件名稱 name: "vendors", priority: -10 // 抽取優先級 }, commons: { // 抽離自定義工具庫 name: "common", priority: -20, // 抽取優先級 minChunks: 2, // 表示將引用模塊如不一樣文件引用了多少次,才能分離生成新chunk minSize: 0 // 將引用模塊分離成新代碼文件的最小體積 } } }
minimizer
代碼壓縮 僅當mode='production'
時生效。
具體配置以及說明可參見以下代碼:
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin"); const TerserPlugin = require("terser-webpack-plugin"); minimizer: [ // 對生成的CSS文件進行壓縮 new OptimizeCssAssetsWebpackPlugin({ cssProcessorPluginOptions: { // options 去掉註釋 preset: ["default", { discardComments: { removeAll: true } }] } }), // 壓縮js new TerserPlugin({ minify: (file, sourceMap) => { // https://github.com/mishoo/UglifyJS2#minify-options const uglifyJsOptions = { /* your `uglify-js` package options */ output: { // 去掉註釋 comments: false }, compress: { // 去掉控制檯打印 drop_debugger: true, drop_console: true } }; if (sourceMap) { uglifyJsOptions.sourceMap = { content: sourceMap }; } return require("uglify-js").minify(file, uglifyJsOptions); } }) ]
runtimeChunk
爲 webpack
運行時代碼建立單獨的 chunk
。
詳細說明可參見官方說明
runtimeChunk: { name: "manifest" }
開發環境的配置,可參見webpack
開發環境。
自動編譯官方列舉了三種方式,這裏我使用的是webpack-dev-server
模塊。詳細配置項可參見官方說明。
具體配置以及說明可參見以下代碼webpack.config.dev.js
:
const chalk = require("chalk"); // 改變命令行中輸出日誌顏色插件 const ip = require("ip").address(); // source-map控制檯追尋到源代碼的文件。 devtool: "inline-source-map", devServer: { // 運行時的目錄 contentBase: path.resolve(__dirname, "dev"), // 當使用 HTML5 History API 時,任意的 404 響應均可能須要被替代爲 index.html。 historyApiFallback: true, // 指定使用一個 host。默認是 localhost。 host: ip, // 控制檯顯示啓動過程進度 progress: true, // 當出現編譯器錯誤或警告時,在瀏覽器中顯示全屏覆蓋。默認狀況下禁用。 overlay: true, // 自動打開瀏覽器 open: true, // 啓用 webpack 的模塊熱替換特性 hot: true, after() { console.log(chalk.cyan(`http://${ip}:${this.port} 已成功打開`)); } } // plugins配置項中添加 new webpack.HotModuleReplacementPlugin() ,用於模塊的熱更新。
devServer
中的配置項通常也能夠在npx
命令中配置使用,這樣可使用一個config
文件,來條件編譯便可。
package.json
中的npx
命令示例:
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "watch": "webpack --watch", "start": "webpack-dev-server --config=webpack.config.dev.js", "dev": "cross-env NODE_ENV=development webpack --progress --colors --devtool cheap-module-source-map", "build": "webpack --progress --colors" }
cross-env
模塊可在命令中定義環境變量。cross-env NODE_ENV=development
,在這裏定義了環境變量,就能夠在配置文件webpack.config.js
中得到並使用這個變量,以處理條件編譯。
得到環境變量:const env = process.env.NODE_ENV
最後可參見個人一個小demo:https://gitee.com/wtto00/webpack-demo