uniapp关于h5说明
https://ask.dcloud.net.cn/article/36279
vender体积过大原因,是第三方import形式的vue、uview、crypto加密等都会打包为一个,因此很大。
解决办法
0 assets图片更改至static
1 webpack-bundle-analyzer 依赖视图分析
2 分割vendor、取消打包console
3 压缩gzip
4 cdn分离
5 更新uni-cli
cnpm install --save-dev webpack-bundle-analyzer
module.exports = {
...
productionSourceMap: false,
lintOnSave: false, // 关闭eslint
...
chainWebpack: config => {
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
}
}
准备前 assets图片路径修改
assets中图片是会打包默认进vendor中的,可以考虑非常用或首屏图片资源路径到static。
打包vendor会明显减少。
https://www.jianshu.com/p/8f4eb5c16fce
一 webpack-bundle-analyzer
webpack-bundle-analyzer 用来看下哪部分过大导致。可以修改写法或替换资源小的版本。
如果每次构建127.0.01:8888 被占用可以修改vue.config.js
uni文档取消console https://uniapp.dcloud.net.cn/collocation/vue-config.html
https://uniapp.dcloud.net.cn/collocation/vue-config.html
const path = require('path')
// const CopyWebpackPlugin = require('copy-webpack-plugin')
// gzip压缩
const CompressionWebpackPlugin = require('compression-webpack-plugin') // 开启压缩
// cdn 配置兼容需要
// const HtmlWebpackPlugin = require('html-webpack-plugin')
// 依赖分析引入
let BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const { log } = require('console')
const isProduction = process.env.NODE_ENV === 'production'
function resolve(dir) {
return path.join(__dirname, dir)
}
// cdn链接
// const cdn = {
// externals: {
// vue: 'Vue'
// // 'vue-router': 'VueRouter',
// // vuex: 'Vuex',
// // "element-ui": "ELEMENT"
// },
// css: [
// // 'https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.9/theme-chalk/index.min.css',
// ],
// js: [
// 'https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js'
// // 'https://cdn.jsdelivr.net/npm/vue-router@3.2.0/dist/vue-router.min.js',
// // 'https://cdn.jsdelivr.net/npm/vuex@3.4.0/dist/vuex.min.js',
// // 'https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.9/index.min.js'
// ]
// }
module.exports = {
productionSourceMap: false,
lintOnSave: false, // 关闭eslint
chainWebpack: config => {
config.resolve.alias.set('@', resolve('src'))
config.optimization.minimizer('terser').tap(args => {
const compress = args[0].terserOptions.compress
// 非 App 平台移除 console 代码(包含所有 console 方法,如 log,debug,info...)
compress.drop_console = true
compress.pure_funcs = [
'__f__' // App 平台 vue 移除日志代码
// 'console.debug' // 可移除指定的 console 方法
]
return args
})
// config.when(isProduction, config => {
// // 我们希望的是在生产环境下才进行cdn优化!!!这点理解很重要。
// // 告诉webpack需要排除的依赖名称和挂载在window上的对象属性名称。
// config.set('externals', cdn.externals)
// // 这里的作用是在后面index.html页面中通过link,script标签加载这些cdn链接。
// config
// .plugin('html')
// .use(HtmlWebpackPlugin)
// .tap(args => {
// args.cdn = cdn
// return args
// })
// })
},
configureWebpack: config => {
if (isProduction) {
config.resolve.alias['bn.js'] = path.resolve(process.cwd(), 'node_modules', 'bn.js')
// gzip压缩
// config.plugins.push(
// new CompressionWebpackPlugin({
// filename: '[path].gz[query]',
// algorithm: 'gzip',
// test: /\.js$|\.html$|.\css/,
// threshold: 10240, // 只有大小大于该值的资源会被处理 10240
// minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
// deleteOriginalAssets: false // 删除原文件
// })
// )
// 用cdn方式引入,则构建时要忽略相关资源
// if (isProduction || devNeedCdn) {
// config.externals = cdn.externals
// }
// 开启分离js h5时打开使用
config.optimization = {
runtimeChunk: 'single',
}
// 依赖分析
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'static', //可选值有server static disabled
generateStatsFile: false,
statsOptions: { source: false },
openAnalyzer: true
})
)
// 取消webpack警告的性能提示
config.performance = {
hints: 'warning',
//入口起点的最大体积
maxEntrypointSize: 50000000,
//生成文件的最大体积
maxAssetSize: 30000000,
//只给出 js 文件的性能提示
assetFilter: function(assetFilename) {
return assetFilename.endsWith('.js')
}
}
}
}
}
参考分析如参考
1 u-picker uivew中存在area和city,实际没有用到,只是因为u-picker自带省市选择就被一并打包存在可优化空间,例如替换为u-select。
https://github.com/umicro/uView/issues/292
// uiew2.x 看起来是优化过了,但1x还是得手动
mport provinces from '../../libs/util/province.js';
import citys from '../../libs/util/city.js';
import areas from '../../libs/util/area.js';
1,可能用不上这些数据;
2,这些数据可能不适合所有人(我另外做了一个);
3,这些东西加上,主包增加了100多K,不划算。
所以,我清空了这三个文件。
2 lodash发现打包整个大概70多k了,实际可以下列方式具体搜索相关
import debounce from 'lodash/debounce'
import groupBy from 'lodash/groupBy'
3 u-toast u-checkbox 这种uview打包其实uniapp自带的组件差异不大可以用自带的写。
例如u-toast等于
this.$toast用法
// 替换uview减少最终打包
Vue.prototype.$toast = (txt, callback = () => {}) => {
uni.showToast({
title: txt,
icon: 'none',
success: callback()
})
}
二 分割js为小部分js文件
更多来源参考: https://blog.csdn.net/weixin_42289080/article/details/119893347
// vue.config.js
const isProduction = process.env.NODE_ENV === 'production'
module.exports = {
configureWebpack: config => {
if (isProduction) {
// 开启分离js
config.optimization = {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all', // 可选值:all,async 和 initial。all功能最强大,所以咱们就使用all
maxInitialRequests: Infinity, // 最大并行请求数,为了以防万一,设置无穷大即可
minSize: 20000, // 引入的模块大于20kb才做代码分割,官方默认20000,这里不用修改了
maxSize: 60000, // 若引入的模块大于60kb,则告诉webpack尝试再进行拆分
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 使用正则匹配node_modules中引入的模块
priority: -10, // 优先级值越大优先级越高,默认-10,不用修改
name(module) { // 设定分包以后的文件模块名字,按照包名字替换拼接一下
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]
return `npm.${packageName.replace('@', '')}`
},
},
},
}
}
}
}
}
publi/index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.documentElement.style.fontSize = document.documentElement.clientWidth / 20 + 'px'
})
var coverSupport =
'CSS' in window &&
typeof CSS.supports === 'function' &&
(CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') +
'" />'
)
</script>
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
<!-- 使用CDN的CSS文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %>
</head>
<body>
<noscript>
<strong>Please enable JavaScript to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<!-- 使用CDN的JS文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
</body>
</html>
三 gzip服务端配合开启,基本线上环境都开了,既节约带宽又提升加载速度,类似阿里云也会自动静态资源优化。
有时高版本会无响应报错
cnpm install --save-dev compression-webpack-plugin@3.1.0
vue.config.js
const isProduction = process.env.NODE_ENV === 'production'
// gzip压缩
const CompressionWebpackPlugin = require('compression-webpack-plugin') // 开启压缩
module.exports = {
productionSourceMap: false,
configureWebpack: config => {
if (isProduction) {
// 如果依赖分析图中比如多次打包bn.js xx.js 可以提取对应只打包一次
// config.resolve.alias['bn.js'] = path.resolve(process.cwd(), 'node_modules', 'bn.js')
config.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.html$|.\css/,
threshold: 10240, // 只有大小大于该值的资源会被处理 10240
minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
deleteOriginalAssets: false // 删除原文件
})
)
}
}
}
四 分离常见的cdn资源,结合vue.config.js 中配置webpack提取常见固定不怎么改变的部分 vue、vue-router等
未成功,其余可参考
https://blog.csdn.net/qq_34191778/article/details/126202249
例如lodash体积过大,打包会整个,可以改import {xx} from 'lodash' 为import xx from 'lodash/xx'
https://www.jianshu.com/p/f03ff4f3a8b3
五 更新uni-cli
uni-cli会影响打包拆分后npm.dcloudio.xx大小,不同版本可能差异达100多k
npm install @dcloudio/uni-automator --save-dev
https://zh.uniapp.dcloud.io/worktile/auto/uniapp-cli-project.html