webpack4搭建vue多页面环境
总结一下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