總結一下webpack4配置vue開發環境,本文不具體介紹webpack的基本概念和用途,如有不了解的請參見https://www.webpackjs.com/concepts/官網
一、webpack基本環境配置
本機系統:centOS、node版本:v10.19.0、npm版本:6.13.4
1、創建項目
mkdir vuepro //創建項目目錄 cd vuepro npm init
npm init 之后一路回車創建好項目
2、配置webpack
npm i webpack webpack-cli -D mkdir src //創建src和config目錄,並創建對應文件 touch src/index.js mkdir config touch config/webpack.common.js
3、webpack.common.js文件基本配置
const path = require('path'); module.exports = { mode:'development', entry: path.resolve(__dirname,'../src/index.js'), output: { filename: '[name].[hash:4].js', // 打包后的文件名稱 path: path.resolve(__dirname,'../dist') // 打包后的文件目錄 } }
並且在package.json中加上打包執行的文件:
index.js里隨便寫一些js內容如:
執行:
npm run build
控制台成功打包並輸出在dist文件下
4、清空打包目錄
npm i clean-webpack-plugin -D
const { CleanWebpackPlugin } = require('clean-webpack-plugin') new CleanWebpackPlugin()
5、配置html模板
npm i html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin') new HtmlWebpackPlugin({ title: 'index', filename: 'index.html', template:path.resolve(__dirname,'../template/index.html') }) mkdir template touch temloate/index.html
並在index.html中寫入基本的html骨架,此時的webpack.common.js:
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { mode:'development', entry: path.resolve(__dirname,'../src/index.js'), output: { filename: '[name].[hash:4].js', // 打包后的文件名稱 path: path.resolve(__dirname,'../dist') // 打包后的文件目錄 }, plugins:[ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'index', filename: 'index.html', template:path.resolve(__dirname,'../template/index.html') }) ] }
此時運行npm run build 在dist目錄上應該生成一個html文件和一個js文件,並且js文件直接注入了html中
在瀏覽器打開index.html並打開控制台,就能看到我們在js里寫的conso語句已經執行了
我們配置的mode:'development'在js里是能通過process.env.NODE_ENV獲取到的;但是在配置文件里,我們是訪問不到process.env.NODE_ENV的比如,在webpack.common.js加入
然后執行npm run build
可見在process.env里是沒有NODE_ENV變量的
6、配置cross-env定義環境變量
npm i -D cross-env
//把package.json的buil改為
"build": "cross-env NODE_ENV=development webpack --config config/webpack.common.js"
此時在執行npm run build 配置文件里就能訪問到process.env.NODE_ENV了
從這里開始不再一步一步搭建,而是直接使用我搭建好的配置,完整的配置地址:https://github.com/jiangconghu01/webpackpro.git
7、配置moudle處理css並分離
npm i style-loader css-loader mini-css-extract-plugin -D const MiniCssExtractPlugin = require("mini-css-extract-plugin") const isDev = process.env.NODE_ENV === 'development' module: { rules: [ { test: /\.css$/, use: [ isDev ? 'style-loader' : MiniCssExtractPlugin.loader, 'css-loader' ] }] }
8 、處理js
可以轉化es6之后新語法為瀏覽器可執行的es5語法,並且在使用新的api和內置對象可以自動polyfill;當然之前使用
1.import "babel-polyfill";
2.module.exports = {
entry: ["babel-polyfill", "./app/js"]
}
;
這種方式全局注入也是可以的,不過這里不使用這種方式
npm i babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime -D npm i core-js@2 -S { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets:[ ['@babel/preset-env',{"useBuiltIns": "usage","corejs": 2}]//這里要加[],要不會報錯 ], plugins:["@babel/plugin-transform-runtime"] } } },
具體的babel7的配置參考:https://juejin.im/post/5ddff3abe51d4502d56bd143
9、處理scss文件
npm i autoprefixer node-sass sass-loader postcss-loader -D
{ test: /\.scss$/, use: [isDev ? 'style-loader' : MiniCssExtractPlugin.loader, 'css-loader', { loader:'postcss-loader', options:{ plugins:[require('autoprefixer')] } }, 'sass-loader' ] }
並使用autoprefixer自動注入瀏覽器兼容前綴,配置之后在package.json中加入
browerslist配置就能自動注入前綴了,具體配置規則可以看https://www.npmjs.com/package/browserslist
10、處理圖片,字體文件等配置
npm i url-loader file-loader -D
{ test: /\.(png|svg|jpg|jpeg|gif)$/, use: [{ loader: 'url-loader', options: { esModule: false, limit: 1024 * 3, // 3k一下的圖片轉為bs64編碼 name: 'resources/[name].[hash:8].[ext]' } } ] }, { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [{ loader: 'file-loader', options: { limit: 1024, name: 'resources/[name].[hash:8].[ext]' } }
11、使用開發服務器webpakc-dev-server
mode: 'development', devServer: { contentBase: path.join(__dirname, '../dist'), index: 'proindex.html', compress: true, hot: true, host: '0.0.0.0', port: 9000, proxy: { '/czxt': { target: 'http://39.105.122.153:3000', changeOrigin: true, secure: false } } }
這里proxy配置改寫不同接口和地址
12、處理vue文件
npm i vue-loader -D const VueLoaderPlugin = require('vue-loader/lib/plugin') new VueLoaderPlugin() { test:/\.vue$/, use:['vue-loader'] }
13、配置resolve
配置可以省略后綴,還有經常飲用文件路徑的別名,提高代碼書寫效率
resolve: { extensions: [".json", ".js", ".jsx",".vue"], alias: { "@": path.join(__dirname, "../src"), 'pages': path.join(__dirname, "../src/pages") } }
14、配置打包顯示進度和時間,配置打包分析結果
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin const ProgressBarPlugin = require('progress-bar-webpack-plugin') new ProgressBarPlugin({ // 顯示進度 format: chalk.green('Progressing') + '[:bar]' + chalk.green(':percent') + '(:elapsed seconds)', clear: false }), new BundleAnalyzerPlugin({ openAnalyzer: false, analyzerMode: 'static', reportFilename: 'bundle_analyzer_report.html' })
到這里基本配置的內容都差不多了
二、優化配置
1、為了減少打包體積,壓縮文件
1.1、 壓縮圖片:之前的配置里,處理圖片的url-loader對小圖(limit限制大小)轉化為base64編碼減少請求,在此之前我們先使用mage-webpack-loader
對圖片壓縮
brew install libpng //先裝libpng,brew是mac的安裝工具 cnpm install image-webpack-loader -D//npm 沒安成功,我換了cnpm { test: /\.(png|svg|jpg|jpeg|gif)$/, use: [{ loader: 'url-loader', options: { esModule: false, limit: 1024 * 3, // 3k一下的圖片轉為bs64編碼 name: 'resources/[name].[hash:8].[ext]' } }, { // 壓縮圖片 loader: 'image-webpack-loader', options: { disable: false } }]
}
可以對比小配置前后的打包大小,比如這個titile的png圖片:不壓縮之前
配置壓縮以后:
原來10.5k,現在5.94k
1.2、 壓縮css
npm i optimize-css-assets-webpack-plugin -D const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin') new MiniCssExtractPlugin({ filename: 'css/[name].style.css' }), new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.style\.css$/g, cssProcessor: require('cssnano'), cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, canPrint: true }),
根據前邊的module里css和scss的配置
分離出來的css都放在(filename: 'css/[name].style.css')css文件夾下,並且有.style.css命名規則,所以配置壓縮范圍:assetNameRegExp: /\.style\.css$/g
1.3、 壓縮js
webpack4直接配置
optimization:{ splitChunks: { cacheGroups: { commons: { name: "commons", chunks: "initial", minSize:0, //代碼最小多大,進行抽離 minChunks:2, //代碼復 2 次以上的抽離 priority: 1 }, vendors: { test: /node_modules/, name: 'vendors', minSize: 0, minChunks: 1, chunks: 'initial', priority: 10 } } } }
提取所有node_modules里的庫代碼到vendors里,提取代碼里的公共代碼到common里,當然這樣也有問題,在引入很多不同的庫時候,就是vendors會很大
所以這里有兩個問題:
1)、每次打包都要打包node_modules目錄下引入的庫和框架代碼,打包速度特別慢
2)、vendors文件很大,頁面加載慢,等待時間長
1、針對打包速度慢的問題,可以使用DllPlugin DllReferencePlugin插件將node_modules下的框架和庫代碼打包成一個文件,直接引入html模板里,這樣只要版本不變,不用每次打包node_modules下的文件,提高了打包速度;但是沒有解決vendors特別大的問題,當然也可以每個庫單獨打包引入,但是這樣特別麻煩,多頁面時候,每個html都要引入
2、針對vendors很大的問題,可以像下邊這樣把庫都分開打包,分開引入,但是這樣打包速度提不上了
還有就是引用cdn資源了,既能提高打包速度,又不用吧第三方庫打包成很大的vendors,還能提高加載速度
在html中引入
然后配置
externals: { 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex': 'Vuex', 'echarts': 'echarts', 'axios': 'axios' },
把項目文件里的這些庫的引入全部去掉
原來打包速度:
不用打包框架和庫代碼之后:
3、多頁配置
一般,在entry加多個入口,然后每個入口對應一個html,每次新加一個文件時候就在配置文件加一個入口,然后new一個HtmlWebpackPlugin,當頁面很多時候你就得反復修改配置文件,所以我我們借助node的glob模塊對項目下的文件進行遍歷,動態輸出配置入口和plugin
const glob = require('glob') const path = require('path') const entryFile = glob.sync(path.join(__dirname,'../src/*.js')) const HtmlWebpackPlugin=require('html-webpack-plugin'); const entry = {} const htmlWebpackPlugins = [] entryFile.forEach(file => { const filename = path.basename(file.split('/').pop(), '.js') entry[filename] = [file], htmlWebpackPlugins.push( new HtmlWebpackPlugin({ title: filename, chunks:['vendors','commons',filename], template: path.resolve(__dirname,`../template/${filename}.html`), filename: `${filename}.html` }) ) }) console.log(entry) module.exports = { entry, plugins:htmlWebpackPlugins }
現在只要每次在src下創建入口文件,然后在template文件下創建對應的html模板文件就行。
4、懶加載的配置
npm i @babel/plugin-syntax-dynamic-import -D { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets:[ ['@babel/preset-env',{"useBuiltIns": "usage","corejs": 2,modules: false}]//這里要加[],要不會報錯 ], plugins:["@babel/plugin-transform-runtime",'@babel/plugin-syntax-dynamic-import'] } } }
修改代碼中如路由為動態加載
5、緩存打包結果,提高編譯效率
npm i cache-loader -D
添加cache-loader之后再次啟動開發環境也變快了,第二次編譯只用了
當然,用了測試的這個demo項目就十多個文件,幾百行代碼
注:本次測試所有文件地址:https://github.com/jiangconghu01/webpackpro.git