问题说明:打包导致 js 很大,然后访问特别慢。
Q:如果你的 js 达到了好几M,(除了个别情况,比如的代码量真的超级大到不行,其实这个本身就不成立)。我最开始就是,打包了我的 app.js 是 20M,网站基本瘫痪。
A:不用考虑了,你的打包有问题。我当初的问题是我把 静态的json (基本都是这个问题)给打包进去了。
B:由于vue是单页应用只有一个入口,导致所有依赖都打包到app.js中导入代码体积过大
1.项目背景
是由webpack生成的vue项目,webpack大版本为3
2.打包出来的体积过大达到20几M
解决A:
未修改前app体积:
排查问题 发现是import的方式引入了json文件导致
修改后app体积:减少了13M,代码压缩至1.5MB
使用以下axios方式处理
解决B:
2.1使用webpack-bundle-analyzer生成报告
是一个用于分析 webpack 打包结果的插件,它可以帮助开发者直观地了解打包后的文件大小、模块依赖关系等信息,从而进行优化。以下是使用 webpack-bundle-analyzer
的基本步骤
发现app.js这个包里面几乎包含了所有的js文件 我们要做的是把这些大的js文件从app.js文件中抽离出来 从而减小app.js的体积 使用 CommonsChunkPlugin插件
优化前:
优化后:明显看到了app.js从原来的10mb变化成198kb
2.2 使用 CommonsChunkPlugin插件配置如下:
2.3 chunks指定某个入口文件中提取公共代码
ComponentA.vue
<template>
<div>Component A</div>
</template>
<script>
import '../test.js'; // 引入公共文件
export default {
name: 'ComponentA'
};
</script>
ComponentB.vue
<template>
<div>Component B</div>
</template><script>
import '../test.js'; // 引入公共文件export default {
name: 'ComponentB'
};
</script>
配置如下:
const path = require('path');
const webpack = require('webpack');module.exports = {
entry: {
main: './src/main.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
chunks: ['main'], // 指定从 main 入口中提取公共模块
minChunks: function(module) {
return module.resource && module.resource.indexOf('test.js') !== -1; // 指定某个文件//return module.resource && module.resource.includes('\\src\\common'); // 指定文件夹
}
})
]
};
未拆分前 :
拆分后:
注意的是router.js文件不能直接指定main这个chunk拆分出来
3.vuecli2脚手架生成webpack模板的项目基本配置详解
1.优化 devtool 中的 source-map ,productionGzip:true gzip静态资源压缩
dev-tool 提供了很多种选项,用来增强我们 debug 的能力,我们熟知的有: source-map , inline-source-map , cheap-source-map 等等。详细的用法可以参考Devtool官方文档,Devtool配置对比 , webpack sourcemap 选项多种模式的一些解释 , https://webpack.github.io/docs/configuration.html#devtool 如果你的文件在打包之后突然变成好几M,那么不用想,肯定是因为 source-map 的原因。 source-map 在开发阶段确实很好用,调试起来很方便,但是在生产环境下http://就没必要部署了。 建议在 prod 环境下关闭 source-map
2. extract-text-webpack-plugin从vue文件中剥离css,单独打包
其主要作用是将CSS样式从JavaScript (vue页面也是js文件中)抽离出来,防止样式被打包进JS文件中引起页面样式加载错乱的现象
注意的是不会删除未使用的css 样式
安装 webpack 插件 extract-text-webpack-plugin 。 npm install extract-text-webpack-plugin --save-dev 。 使用方法:
plugins: [
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
allChunks: true,
}),
]
这里使用了 contenthash , webpack 会根据内容去生成 hash 值。
3.使用 UglifyJSPlugin 压缩。
UglifyJsPlugin是一个用于压缩JavaScript代码的webpack插件。它的主要作用是将代码中的空格、注释、无效代码等进行压缩,从而减小文件的大小,提高加载速度,并不是生成压缩包文件
通过 UglifyJSPlugin 可以压缩我们的 *.js 文件。 安装方法: npm install uglifyjs-webpack-plugin --save-dev
plugins:[
new UglifyJsPlugin({
uglifyOptions: {
compress: {
// 警告配置
warnings: false,
// 删除所有的`console`语句
drop_console: true,
// 内嵌定义了但是只用到一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量去引用的静态值
reduce_vars: true,
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
]
prod打包默认开启了Tree-shaking:
test1.js
export default 'hell0!!!'
export function cookie1(a, b) {
// loga,b
console.log(a + b);
}
a.vue
import test, { cookie1 } from "./test1";
export default {
name: "HelloWorld",
data() {
return {
msg: "Welcome to Your Vue.js App",
};
},
mounted() {
console.log(test);
cookie1(10, 20); //调用是第一种情况 ;不调用是第二种情况
},
};
4.提取公共依赖 CommonsChunkPlugin 插件
CommonsChunkPlugin
是 Webpack 3 及其更早版本中的一个插件,用于优化和分离代码,将公共模块提取到单独的文件中,从而实现代码复用和减少重复加载
使用 CommonsChunkPlugin 插件,将多个 js 文件进行提取,建立一个独立的文件。这个文件包含一些共用模块,浏这样览器只在刚开始的时候加载一次,便缓存起来供后续使用。而不用每次访问一个新界面时,再去加载一个更大的文件。
作用
- 分离共享代码:将多个入口文件之间的共享代码提取到一个单独的 chunk 中,以减少冗余代码。
- 降低重复引入:避免在多个入口文件中重复引入同一个模块,减小打包后的文件体积。
- 提高缓存效率:由于公共模块被提取到单独的文件,这些文件如果没有变化,可以被浏览器缓存,从而提升加载性能。
示例
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
app: './src/app.js',
vendor: ['react', 'react-dom'] // 假设我们使用了 React
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor', // 指定提取公共代码到哪个 chunk
minChunks: Infinity,
// 或者可以指定一个函数来决定哪些模块应该被提取出来
// minChunks: (module) => {
// // 任何在 node_modules 中的模块都会被提取到 vendor chunk
// return module.context && module.context.includes('node_modules');
// }
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest', // 用于提取 webpack 运行时代码,防止其频繁变动影响缓存
minChunks: Infinity
})
]
};
在这个示例中:
entry
定义了两个入口:app
和vendor
。vendor
包含了外部库(例如 React)。- 第一个
CommonsChunkPlugin
实例将vendor
入口和其他入口共享的模块提取到vendor
chunk 中。 - 第二个
CommonsChunkPlugin
实例提取manifest
,用于存放 Webpack 运行时代码。
在 Webpack 4 及其更高版本中,CommonsChunkPlugin
已被废弃,取而代之的是 optimization.splitChunks
和 optimization.runtimeChunk
选项。这些新的配置选项提供了更强大和灵活的方式来进行代码分割和优化。
实际在项目的使用如下
优化缓存:通过将所有第三方库提取到单独的 vendor chunk 中,如果应用代码发生变化但第三方库没有变化,浏览器仍然可以从缓存中加载 vendor 文件,而不需要重新下载
plugins:[
new webpack.optimize.CommonsChunkPlugin({//这里把node_modules文件夹的依赖都打入到vendor文件中
name: 'vendor',
minChunks (module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
]
1.main.js 引入echart依赖后能看到vendor.js包体积明显增加了由之前的132KB增加到1.2mb
引入后:
5.开启gzip压缩(这个插件可不使用,在nginx中一样可做配置还能解压打包时长)
把css js 压缩成.zip格式文件
我们使用 compression-webpack-plugin 插件进行压缩。 安装: npm install compression-webpack-plugin --save-dev 。 compression-webpack-plugin 详细用法 使用:
plugins:[
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
]
开启html压缩,自动添加上面生成的静态资源
添加插件 html-webpack-plugin
安装: npm install html-webpack-plugin --save-dev 用法:
plugins:[
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
}),
]
6. nginx 开启:gzip, 打包生成压缩包部署到线上需要后台的配合设置
当然你学习下nginx配置也可自己配置http缓存及http2配置-CSDN博客
http {
#其他配置
gzip on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/json;
gzip_buffers 4 16k;
gzip_vary on;
gzip_http_version 1.1;
}
7.externals不打包第三方库 用cdn的方式引入
项目在公网部署可以使用,若在政务外网就不行
减少 vendor.js 的体积,从本质上来解决这种问题。
除了vue.js,还有其它第三方库,比如element-ui,layer等优秀的插件和框架都可以通过这种方式来解决。
测试将 vue.js 不打包
module.exports = {
externals: {
'vue': 'Vue'
},
plugins:[]
}
index.html scprit标签引入
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.2.6/vue.common.js"></script>
8.路由懒加载
懒加载(Lazy Loading)是一种性能优化技术,它允许你在实际需要时再加载某些资源,而不是在应用初始化时一次性加载所有资源。这可以显著减少初始加载时间,提高用户体验。
不使用懒加载的路由
index.vue
<template>
<div>
<h1 @click="jump()">index页面</h1>
</div>
</template>
<script type="text/ecmascript-6">
export default {
data() {
return {
}
},
methods:{
jump() {
this.$router.push("/one");
}
}
}
</script>
one.vue/two页面类似
<template>
<div class="hello">
<h1 @click="jump">{{ msg }}</h1>
<h2>Essential Links</h2>
</div>
</template>
<script>
import test from "../test.js";
console.log(test);
export default {
name: "HelloWorld",
data() {
return {
msg: "one页面",
};
},
created() {
console.log("one 页面created输出");
},
mounted() {
console.log("one 页面mounted输出");
},
methods: {
jump() {
this.$router.push("/two");
},
},
};
</script>
最大的副作用会增加app.js体积及log的输出
使用路由懒加载后app.js包体积明显减小了
建议是路由懒加载搭配new webpack.optimize.CommonsChunkPlugin使用
Vue Webpack 打包优化——路由懒加载(按需加载)原理讲解及使用方法_vue懒加载的原理及实现_杰~JIE的博客-CSDN博客