写在前面
因为业务关系,涉及到的新老业务较多。因此接触过webpack早期与后期的阶段。
以及vue-cli2、3、4
我们现在已经在使用vue-cli4了
老生常谈的几个优化操作
Dll
剥离公用资源
如何使用(vue-li3、4)的小伙伴可以看以下
先将dll配置文件写好
webpack.dll.config.js
const path = require('path');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const utils = require('../config/utils');
const packageSysName = require('../package.json').name;
// 这个操作是获取name,打包的时候植入自己的对应的系统 可删除
const sysName = utils.getSystemName(packageSysName);
// 这个操作是获取name,打包的时候植入自己的对应的系统 可删除
const resolve = dir => path.join(__dirname, '..', dir);
module.exports = {
entry: {
vue: ['vue', 'vuex', 'vue-router', 'axios'],
ec: ['echarts'],
utils: ['moment'],
ui: ['element-ui']
},
// devtool:'source-map',
output: {
path: path.join(__dirname, '..', 'public/vendor'),
filename: '[name].dll.js',
library: '[name]_[hash]'
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, '..', 'public/vendor', '[name]-manifest.json'),
name: '[name]_[hash]',
context: process.cwd()
}),
new CopyWebpackPlugin([{
from: resolve('./public/vendor'),
to: resolve(`./dist/resources/${sysName}/assets/vendor`),
toType: 'dir'
}])
],
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js'
}
}
};
引入此配置文件于vue.config.js中(vue-cli3、4)
dllEntry.forEach(dll => {
result.push(`resources/${sysName}/assets/vendor/${dll}.dll.js`)
});
if (IS_PROD) {
Object.keys(externalsMaps.map).forEach(exter => {
const {
name,
version
} = externalsMaps.map[exter];
result.push(`${name}/v${version}/${name}.js`);
result.push(`${name}/v${version}/${name}.css`);
});
}
return result;
最后使用 html-webpack-tags-plugin 此插件
对其生成的文件在编译过程中自动插入html文件中
静态资源的处理
将css资源单独打包
以下提供案例是webpack 4.39.2的
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// all options are optional
filename: `${name}.css`,
chunkFilename: '[name].chunk.css'
});
//loader部分
{
test: /\.scss$/,
use: [{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development'
}
},
'css-loader',
'postcss-loader',
'sass-loader'
]
}
img
图片文件我们分为几个策略
一般的icon以及小文件,使用svg-sprite的模式进行打包。svg可以改变颜色,这在icon里是十分好用的,因为icon大多都有不同的状态。
以下提供案例依旧是vue-cli4的
config.module
.rule("images")
.test(/\.(svg|png|jpe?g|gif|webp)(\?.*)?$/)
.exclude
.add(resolve('src/assets/image/icons'))
.add(resolve('src/components/menu/icon'))
.add(resolve('src/assets/image/crmMonitor/process'))
.end()
.use('url-loader')
.tap(options => merge(options, {
limit: 8192, //限制图片大小,小的图片将转化为base64
fallback: {
loader: 'file-loader',
options: {
name: IS_PROD ? `${staticResource}/img/[name].[ext]` : `img/[name].[ext]`
}
}
}));
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include
.add(resolve('src/assets/image/icons')) //处理svg目录
.add(resolve('src/components/menu/icon'))
.add(resolve('src/assets/image/crmMonitor/process'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
});
externals
大部分会使用cdn。但是因为我手下的项目都是局域网项目:)
但也难不倒我这样的小天才
因为我在部门内开发了前端类用库。而这部分的库有很多版本迭代以及多人使用。且部分组件是应该按需加载的。
我将其打包到服务器上后,提供了地址(并在其中打上版本号),并用nginx将其拦截转发。
于是此时,我的fake cdn就出现了。
结合dll,与prefetch,preload(什么是prefetch、preload,争取下一篇提及一下。好东西。)可以按需加载。
具体代码下一章来吧~~~
eslint、 gzip、mock(hmr)
eslint
短话短说,语法检查,组内使用的是airbnb的语法。
如何配置?
根目录下=》 .eslintrc.js
参考配置
gzip
直接上vue-cli3、4的代码
config.plugin('compress').use(CompressionWebpackPlugin, [{
algorithm: 'gzip',
test: new RegExp(`\\.(${productionGzipExtensions.join('|')})$`),
threshold: 10240,
minRatio: 0.8,
}])
也可以使用uglifyjs-webpack-plugin
mock
我们使用过express的中间件转发,也使用过webpack-middle-proxy,以及mock.js
但是都不满足我们的需求,首先他要先满足能够hmr(热更新),最好能直接读取json,懒
后来我们选用了mocker-api,比较合适于resetful的接口模式
废话
其实工程化我使用过gulp、webpack两个脚手架。
gulp是比较简单易上手的,所以简单的项目,比如只是简单gzip后使用的js,就会使用gulp。他的pipe链条模式印象深刻。webpackChain有点这个意思。
下一篇会详细说下自己写loader plugin的时候遇到的问题