記一次webpack4.x項目配置
在自構建自己的個人頁面的時候使用到webpack4,遇到了一些問題,查看了大佬們的文章以及官方文檔,在這裏總結一下。
webpack比較基礎的東西就不贅述了,代碼裏面的註釋也會輔助說明,先看一下目錄結構:
│ .babelrc │ .gitignore │ package-lock.json │ package.json │ README.en.md │ README.md │ ├─build │ webpack.common.js │ webpack.dev.js │ webpack.prod.js │ webpack.rules.js │ └─src ├─assets │ test.json │ ├─common │ ├─css │ ├─fonts │ ├─images │ └─js └─pages ├─my │ index.html │ index.js │ index.styl │ └─other index.html index.js index.styl
這裏目錄結構導出如果有不知道的同學,其實很簡單,windows命令 tree /f 導出當前目錄包括文件夾名字,tree /f > catalog.txt 導入到一個txt文本。
1.webpack整體配置
像大部分同學的習慣一樣,在build文件夾裏面分為幾個webpack配置,common基礎公用配置,dev開發環境配置,prod生產環境配置,以及單獨分離出來的rule配置各項loader。
//common module.exports = (env) => { return { entry: {}, plugins: [], optimization: {}, module: {} } };
//dev
module.exports = merge(common(‘development‘), { mode: ‘development‘, devtool: ‘inline-source-map‘, output: {}, devServer: {}, plugins: [], });
//prod
module.exports = merge(common(‘production‘), { mode: ‘production‘, output: {}, plugins: [ ], });
這裏webpack4 推薦用mode聲明開發環境還是生產環境,這裏是作為一個全局變量,而不是node環境,所以如果要在配置裏面用到全局變量,用函數返回
這裏我是直接定義的變量,然後在引用的時候傳入參數,不是官方所定義的全局變量,其實這樣寫不是很好,既然分離了環境那就應該在不同的配置文件中寫配置。
2.多頁面entry配置和html模版插件
webpack裏面的entry
entry: { // 多入口文件 my: [ ‘./src/pages/my/index.js‘, ], other: [ ‘./src/pages/other/index.js‘, ] },
在外部定義多個頁面的信息,以及html-webpack-plugin模版插件的函數進行批量操作
/*可多頁面配置*/ const htmlArray = [ { _html: ‘my‘, title: ‘我的首頁‘, // chunks: [‘my‘] }, { _html: ‘other‘, title: ‘其他‘, // chunks: [‘other‘] } ]; // 獲取html-webpack-plugin參數的方法 let getHtmlConfig = function (name, title, globalEnv) { return { template: `./src/pages/${name}/index.html`, filename: `${name}.html`, // favicon: ‘./favicon.ico‘, title: title, inject: true, hash: false, //開啟hash ?[hash] /*chunk 裏面配置的文件才會在html中引入,所以有其他引入的話要註意加上, 比如runtime和splitChunks裏面的vendor等,建議不要這個,默認加載所有的*/ // chunks: chunks, minify: globalEnv === "development" ? false : { removeComments: true, //移除HTML中的註釋 collapseWhitespace: true, //折疊空白區域 也就是壓縮代碼 removeAttributeQuotes: true, //去除屬性引用 }, }; };
在webpack plugin裏面引入執行html模版
//自動生成html模板 ...htmlArray.map((element) => { return new HtmlWebpackPlugin(getHtmlConfig(element._html, element.title, env)); }),
3.module.rules loader加載器
由於loader比較多,可以單獨提取到一個配置文件
css,css預處理器loader,MiniCssExtractPlugin是webpack4分離css的插件,後面再提到
-
{ test: /\.(css|styl)$/, // 區別開發環境和生成環境 /*用了MiniCssExtractPlugin,不要用style-loader,沖突*/ use: env === "development" ? ["style-loader", "css-loader", "stylus-loader"] : [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"] },
-
{ test: /\.js$/, exclude: "/node_modules/", use: [{ loader: "babel-loader", options: { /*可使用禁止在每個文件註入runtime,避免文件多而大,采用babel-plugin-transform-runtime輔助提取引用 * plugins: [‘@babel/transform-runtime‘]*/ // 配置在 .babelrc 中,和browserslist // presets: [‘@babel/preset-env‘] } }] },
這裏是base64轉換和輸入位置,更多配置可以看官網
-
{ test: /\.(png|jpg|gif)$/, use: [{ // url-loader包含file-loader loader: "url-loader", options: { limit: 5 * 1024, //小於5k時將會已base64位圖片打包處理 // 圖片文件輸出的文件夾 outputPath: "images" } }] },
字體和html的 loader
-
{ test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/, loader: ‘url-loader‘, options: { limit: 10000, /*原來的名字和後綴*/ name: ‘[name].[ext]‘, // 文件輸出的文件夾 outputPath: "fonts" } }, { test: /\.html$/, // html中的img標簽 use: ["html-withimg-loader"] },
4. plugin
common 裏面,第一個是html模版,上面講過了,第二三個顧名思義。
plugins: [ //自動生成html模板 ...htmlArray.map((element) => { return new HtmlWebpackPlugin(getHtmlConfig(element._html, element.title, env)); }), // 消除冗余的css代碼 new PurifyCssWebpack({ paths: glob.sync(path.join(__dirname, "../src/pages/*/*.html")) }), //靜態資源輸出 new CopyWebpackPlugin([{ from: path.resolve(__dirname, "../src/assets"), to: ‘./assets‘, ignore: [‘.*‘] }]), ],
dev,這裏官方提示使用這裏完全啟發devServer熱更新,我沒深入研究,同誌們可以研究一下。
plugins: [ //熱更新,配合devserver服務完全啟動HMR new webpack.HotModuleReplacementPlugin(), // new BundleAnalyzerPlugin(), //性能優化 高大上的可視化分析模塊 ],
prod,清理dist的插件有一點小變動,提取css的插件官方建議被替代,以及仍然需要額外的插件壓縮css
plugins: [ /*刪除dist目錄,2.0後默認了output的path,這裏無需填寫*/ new CleanWebpackPlugin({ root: path.resolve(__dirname, ‘../‘), //根目錄 // verbose Write logs to console. verbose: true, //開啟在控制臺輸出信息 }), /*webpack用這個代替ExtractTextPlugin,提取,開發環境我沒分離*/ new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // both options are optional filename: ‘[name].[contenthash].css‘, // chunkFilename: ‘[id].[contenthash].css‘, }), //壓縮css new OptimizeCSSPlugin(), ],
5. 代碼壓縮和分離
/*代碼分離 壓縮,webpack4x集成部分插件和選項*/ optimization: { /*壓縮js代碼入口,是否開啟minimizer, 例如TerserWebpackPlugin插件,性能比UglifyJSPlugin好 默認引入生產模式為true,所以不用操作,可以手動開啟和調節minimizer選項*/ // minimize: false /*將運行時代碼拆分為單獨的塊。 將其設置single為為所有塊創建單個運行時包 單頁面 runtimeChunk: ‘single‘, */ /*多頁面別名*/ runtimeChunk: { name: entryPoint => `runtimechunk~${entryPoint.name}` }, /*分離公共代碼*/ splitChunks: { /*緩存chunk 提取公共模塊復用*/ cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: ‘vendors‘, chunks: ‘all‘ } } }, },
6. 開發環境devServer
devServer: { contentBase: path.join(__dirname, "../dist"), publicPath:‘/‘, host: "127.0.0.1", port: "5199", overlay: true, // 瀏覽器頁面上顯示錯誤 // open: true, // 開啟瀏覽器 open: ‘Google Chrome‘ // stats: "errors-only", //stats: "errors-only"表示只打印錯誤: hot: true, // 開啟熱更新 // compress: true, //開啟gzip },
7. 生產環境 output 輸出
output: { path: path.resolve(__dirname, ‘../dist‘), // 打包多出口文件 // 生成 a.bundle.[hash].js b.bundle.[hash].js // hash工程級整個是一樣的,chunkhash模塊級有依賴的文件是一樣的,contenthash根據自身的內容生成hash,每個文件都不一樣 filename: ‘./js/[name].[contenthash].js‘, publicPath: ‘./‘ },
8. js 語法和api轉換編譯
開發依賴
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/plugin-transform-runtime": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"babel-loader": "^8.0.5",
生產也需要的依賴
"dependencies": {
"@babel/polyfill": "^7.2.5",
"@babel/runtime": "^7.3.4"
}
其中runtime官方的說法是節約代碼以及生成器語法的轉換,如果不用這兩個使用async和await會報錯。
然後在.babelrc中使用,關於 @babel/polyfill 的使用,這裏配合 @babel/preset-env 有三種使用方式,這裏usage會自動根據代碼轉換,安裝後不要引入。
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage" } ] ], "plugins": [ "@babel/plugin-transform-runtime" ] }
最後在package.json或者單獨建立browserslist文件來限制瀏覽器版本和轉換操作
"browserslist": [
"defaults",
"not ie < 11",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
],
最後啟動和大概測試了下,沒發現什麽問題。
由於時間和能力有限,可能有很多沒考慮到,不夠深入理解,還有一些冗余甚至錯誤的地方望各位大佬指正。
參考:
1,多頁面配置,參考的是這位大佬的文章。https://segmentfault.com/a/1190000014984842
2,webpack官方文檔,可以統一看一遍。https://webpack.js.org/plugins/mini-css-extract-plugin/
3,babel相關官方文檔 https://babeljs.io/docs/en/babel-polyfill#docsNav
附:
1,在線配置webpack的頁面,常用的依賴,插件和代碼分割以及安裝命令等。https://webpack.jakoblind.no/
time:2019-02-15
記一次webpack4.x項目配置