vue+webpack+vue-cli
1.Vue.component()与Vue.use()会导致webpack打包产生的chunk-vendors.js过大会造成首页加首次载缓慢?
Object.values(element).map((e: any)=> {
if (!e.__file && !e.name) return
Vue.component('Ca' + e.name, e)
})
应该提取基础组件例如高频使用的组件加入劝阻注册
2.用手机访问页面只需要加载当前访问的页面,不需要预加载,怎么处理?
20201107
chainWebpack: config => {
config.plugins.delete('preload');
config.plugins.delete('prefetch');
}
3.优化首屏加载速度(减小打包后app.js与chunk-vendors.js),第三方组件按需加载
{
path: '/',
component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
},
@Component({
components: {
Hello:() => import(/* webpackChunkName: "Hello", webpackPrefetch: false */ '../components/HelloWorld.vue')
}
})
2.提取页面公共资源
plugins: [
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'vue',
entry: 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js',
global: 'Vue',
},
{
module: 'vue-router',
entry: 'https://cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',
global: 'VueRouter',
},
{
module: 'google-roboto',
entry: {
path: 'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
type: 'css',
},
},
],
}),
]
3.引用element-ui实现按需加载
{
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
4.webpack使用
optimization: {
splitChunks: {
chunks: 'async|all', // 模块异步
minSize: 20000,// 20k
minRemainingSize: 0,
minChunks: 1, // 被引用次数,到达多少开始抽离
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
},
},
4.在项目中写了很多没有用到的代码,打包到了服务器上,浪费了资源加载怎么处理?
使用Tree Shaking擦除无用的JavaScript和CSS
如下
import('../units/index' /* webpackChunkName: "pl" */).then((content) => {
console.log(content.default())
})
2.
5.CSS优化
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const glob = require('glob')
const PATHS = {
src: path.join(__dirname, 'src')
}
new PurgeCSSPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
})
2.mini-css-extract-plugin:将CSS提取到单独的文件中。它为每个包含CSS的JS文件创建一个CSS文件。它支持CSS和SourceMap的按需加载(vuecli内置了此插件)
chainWebpack(config) {
config.when(process.env.NODE_ENV !== 'development', config => {
config.plugin('extract-css').tap(options => {
options[0].filename = 'static/css/[name].[hash:8].css'
return options
})
}
}
6.安装sass,目前装以下版本,高版本报错
7.压缩图片
config.module
.rule('graphql')
.test(/\.(gif|png|jpe?g|svg)$/i)
.use('file-loader')
.loader('image-webpack-loader')
.tap(options => {
// 修改它的选项...
return options = {
mozjpeg: {
progressive: true,
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
})
.end()
8.gzip优化
const CompressionPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg|ttf|woff)(\?.*)?$/i;
new CompressionPlugin({
test: productionGzipExtensions,
deleteOriginalAssets: true, // 是否删除原资源
}),
9.完整配置
const glob = require('glob')
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg|ttf|woff)(\?.*)?$/i;
const { join } = require('path')
const PATHS = {
src: join(__dirname, 'src')
}
module.exports = {
publicPath: './',
productionSourceMap: false, // 关掉map
configureWebpack: {
plugins: [
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'vue',
entry: 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js',
global: 'Vue',
},
{
module: 'vue-router',
entry: 'https://cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',
global: 'VueRouter',
},
{
module: 'google-roboto',
entry: {
path: 'https://unpkg.com/element-ui/lib/theme-chalk/index.css',
type: 'css',
},
},
],
}),
new PurgeCSSPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
}),
new CompressionPlugin({
test: productionGzipExtensions,
deleteOriginalAssets: true, // 是否删除原资源
}),
]
},
chainWebpack: config => {
config.plugins.delete('preload');
config.plugins.delete('prefetch');
config.optimization.splitChunks({
chunks: 'all',
minSize: 20000,
minChunks: 1,
});
config.module
.rule('image-loader')
.test(/\.(gif|png|jpe?g|svg)$/i)
.use('file-loader')
.loader('image-webpack-loader')
.tap(options => {
// 修改它的选项...
return options = {
mozjpeg: {
progressive: true,
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
})
.end()
}
// devServer: {
// proxy: {
// '/': { //访问路径,可以自己设置,
// target: 'http://xxx:8000/', //代理接口,即后端运行所在的端口
// changeOrigin: true, //设置是否跨域
// ws: true,
// // pathRewrite: { //访问路径重写
// // '^/activity/babao_dan/save': 'sss'
// // }
// }
// }
// }
}
10.动态导出模块
const files = require.context(
directory, // 目录,必须写死
(useSubdirectories = true), // 是否递归
(regExp = /^\.\/.*$/), // 匹配文件
(mode = 'sync') // 同步
);
导出的功能有3个属性:resolve,keys,id。
resolve 是一个函数,并返回已解析请求的模块ID。
keys 是一个函数,它返回上下文模块可以处理的所有可能请求的数组
sync 直接打包到当前文件,同步加载并执行
lazy 延迟加载会分离出单独的 chunk 文件
lazy-once 延迟加载会分离出单独的 chunk 文件,加载过下次再加载直接读取内存里的代码。
eager 不会分离出单独的 chunk 文件,但是会返回 promise,只有调用了 promise 才会执行代码,可以理解为先加载了代码,但是我们可以控制延迟执行这部分代码
/**
* @description: 匹配相应组件方法
* @param {any} 文件信息
* @return {any} 组件信息
*/
function componentFn(files: any) {
const components: any = {};
files.keys().forEach((key: string) => {
const name = (require('path').basename(key, '.vue') || files(key).default.name).toLocaleLowerCase();
const file = files(key).default || files(key);
components[`mr-${name}`] = file;
});
return components;
}