Closed ileadall42 closed 5 years ago
3q
如何实现按需加载对应的文件 目前是一次性全部加载
@ileadall42 你好,我用的是 caddy,也加了 gzip 相关的配置,第一次访问速度还是在 5 到 6 秒才能打开页面,去琢磨了下代码里面,优化空间确实不大了,这个速度算正常吗,咨询下你那边是多长时间,还有别的优化建议吗
办法是有,在 vue.config.js 里面加上压缩的代码,在 nginx.conf 里面加上 gzip,我自己弄了,需要参考代码不
办法是有,在 vue.config.js 里面加上压缩的代码,在 nginx.conf 里面加上 gzip,我自己弄了,需要参考代码不
配置发一下,参考一下吧
@jlsunl 项目整体需要把 ant-design-vue 改成按需加载
nginx.conf 的 http 中加入以下片断
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_static on;
gzip_proxied any;
gzip_min_length 1k;
gzip_comp_level 5;
gzip_buffers 4 16k;
gzip_types text/plain text/javascript text/css text/xml application/javascript application/x-javascript application/xml application/json application/xml+rss image/jpeg image/gif image/png;
gzip_vary off;
gzip_http_version 1.0;
vue.config.js
const path = require('path')
const TerserWebpackPlugin = require('terser-webpack-plugin')
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const keys = require('lodash.keys')
const os = require('os')
const webpack = require('webpack')
const createThemeColorReplacerPlugin = require('./plugins/theme.plugin')
function resolve(dir) {
return path.join(__dirname, dir)
}
const envConfig = require('./src/config/env.config')
const isOnline = !['local'].includes(process.env.mode)
const isProduction = ['prod'].includes(process.env.mode)
const assetsCDN = {
// webpack build externals
externals: {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
axios: 'axios'
},
css: [],
js: [
'//cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
'//cdn.jsdelivr.net/npm/vue-router@3.1.6/dist/vue-router.min.js',
'//cdn.jsdelivr.net/npm/vuex@3.3.0/dist/vuex.min.js',
'//cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js'
]
}
const productionGzipExtensions = ['js', 'css', 'json', 'txt', 'html', 'ico', 'svg']
// vue.config.js
const vueConfig = {
configureWebpack: config => {
// webpack plugins
config.plugins.push(
// Ignore all locale files of moment.js
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
createThemeColorReplacerPlugin()
)
if (isOnline) {
config.plugins.push(
// 开启压缩
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
threshold: 10240,
minRatio: 0.8
}),
new TerserWebpackPlugin({
sourceMap: false,
parallel: false,
terserOptions: {
compress: {
drop_debugger: isProduction,
drop_console: isProduction,
pure_funcs: [] // 移除console
},
beautify: false,
comments: false,
keep_classnames: false,
output: {
comments: false,
}
}
})
)
config.performance = {
hints: 'warning',
// 入口起点的最大体积 整数类型(以字节为单位 500k).
maxEntrypointSize: 500 * 1024,
// 生成文件的最大体积 整数类型(以字节为单位 300k).
maxAssetSize: 300 * 1024,
// 只给出 js 文件的性能提示.
assetFilter: function(assetFilename) {
return assetFilename.endsWith('.js')
}
}
}
// if prod, add externals
config.externals = isOnline ? assetsCDN.externals : {}
},
chainWebpack: (config) => {
config.resolve.alias
.set('@$', resolve('src'))
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
.oneOf('inline')
.resourceQuery(/inline/)
.use('vue-svg-icon-loader')
.loader('vue-svg-icon-loader')
.end()
.end()
.oneOf('external')
.use('file-loader')
.loader('file-loader')
.options({
name: 'assets/[name].[hash:8].[ext]'
})
config.plugin('define').tap(args => {
keys(envConfig[process.env.mode]).forEach(key => {
args[0]['process.env'][key] = JSON.stringify(envConfig[process.env.mode][key])
})
return args
})
if (isOnline) {
// 删除预加载
config.plugins.delete('preload')
config.plugins.delete('prefetch')
config.output.filename('[name].[hash].js').end()
config.plugin('html').tap(args => {
args[0].cdn = assetsCDN
return args
})
}
},
css: {
sourceMap: false,
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
// less vars,customize ant design theme
// 'primary-color': '#F5222D',
// 'link-color': '#F5222D',
'border-radius-base': '2px'
},
// DO NOT REMOVE THIS LINE
javascriptEnabled: true
}
}
}
},
devServer: {
// development server port 3000
port: 3000,
proxy: {
'/api2': {
target: envConfig[process.env.mode].BASE_API_2, // 请求本地需要后台项目
ws: false,
changeOrigin: true,
pathRewrite: {
'/api2': '' // 默认所有请求都加了 api 前缀, 需要去掉
}
},
'/api': {
target: envConfig[process.env.mode].BASE_API, // 请求本地需要后台项目
ws: false,
changeOrigin: true,
pathRewrite: {
'/api': '' // 默认所有请求都加了 api 前缀, 需要去掉
}
}
}
},
parallel: os.cpus().length > 1,
// 如果你不需要生产环境的 source map, 可以将其设置为 false 以加速生产环境构建.
productionSourceMap: false,
lintOnSave: false,
// babel-loader no-ignore node_modules/*
transpileDependencies: ['vue-plyr']
}
module.exports = vueConfig
@jlsunl 项目整体需要把 ant-design-vue 改成按需加载
nginx.conf 的 http 中加入以下片断
gzip on; gzip_disable "MSIE [1-6]\."; gzip_static on; gzip_proxied any; gzip_min_length 1k; gzip_comp_level 5; gzip_buffers 4 16k; gzip_types text/plain text/javascript text/css text/xml application/javascript application/x-javascript application/xml application/json application/xml+rss image/jpeg image/gif image/png; gzip_vary off; gzip_http_version 1.0;
vue.config.js
const path = require('path') const TerserWebpackPlugin = require('terser-webpack-plugin') const CompressionWebpackPlugin = require('compression-webpack-plugin') const keys = require('lodash.keys') const os = require('os') const webpack = require('webpack') const createThemeColorReplacerPlugin = require('./plugins/theme.plugin') function resolve(dir) { return path.join(__dirname, dir) } const envConfig = require('./src/config/env.config') const isOnline = !['local'].includes(process.env.mode) const isProduction = ['prod'].includes(process.env.mode) const assetsCDN = { // webpack build externals externals: { vue: 'Vue', 'vue-router': 'VueRouter', vuex: 'Vuex', axios: 'axios' }, css: [], js: [ '//cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js', '//cdn.jsdelivr.net/npm/vue-router@3.1.6/dist/vue-router.min.js', '//cdn.jsdelivr.net/npm/vuex@3.3.0/dist/vuex.min.js', '//cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js' ] } const productionGzipExtensions = ['js', 'css', 'json', 'txt', 'html', 'ico', 'svg'] // vue.config.js const vueConfig = { configureWebpack: config => { // webpack plugins config.plugins.push( // Ignore all locale files of moment.js new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), createThemeColorReplacerPlugin() ) if (isOnline) { config.plugins.push( // 开启压缩 new CompressionWebpackPlugin({ filename: '[path].gz[query]', algorithm: 'gzip', test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 10240, minRatio: 0.8 }), new TerserWebpackPlugin({ sourceMap: false, parallel: false, terserOptions: { compress: { drop_debugger: isProduction, drop_console: isProduction, pure_funcs: [] // 移除console }, beautify: false, comments: false, keep_classnames: false, output: { comments: false, } } }) ) config.performance = { hints: 'warning', // 入口起点的最大体积 整数类型(以字节为单位 500k). maxEntrypointSize: 500 * 1024, // 生成文件的最大体积 整数类型(以字节为单位 300k). maxAssetSize: 300 * 1024, // 只给出 js 文件的性能提示. assetFilter: function(assetFilename) { return assetFilename.endsWith('.js') } } } // if prod, add externals config.externals = isOnline ? assetsCDN.externals : {} }, chainWebpack: (config) => { config.resolve.alias .set('@$', resolve('src')) const svgRule = config.module.rule('svg') svgRule.uses.clear() svgRule .oneOf('inline') .resourceQuery(/inline/) .use('vue-svg-icon-loader') .loader('vue-svg-icon-loader') .end() .end() .oneOf('external') .use('file-loader') .loader('file-loader') .options({ name: 'assets/[name].[hash:8].[ext]' }) config.plugin('define').tap(args => { keys(envConfig[process.env.mode]).forEach(key => { args[0]['process.env'][key] = JSON.stringify(envConfig[process.env.mode][key]) }) return args }) if (isOnline) { // 删除预加载 config.plugins.delete('preload') config.plugins.delete('prefetch') config.output.filename('[name].[hash].js').end() config.plugin('html').tap(args => { args[0].cdn = assetsCDN return args }) } }, css: { sourceMap: false, loaderOptions: { less: { lessOptions: { modifyVars: { // less vars,customize ant design theme // 'primary-color': '#F5222D', // 'link-color': '#F5222D', 'border-radius-base': '2px' }, // DO NOT REMOVE THIS LINE javascriptEnabled: true } } } }, devServer: { // development server port 3000 port: 3000, proxy: { '/api2': { target: envConfig[process.env.mode].BASE_API_2, // 请求本地需要后台项目 ws: false, changeOrigin: true, pathRewrite: { '/api2': '' // 默认所有请求都加了 api 前缀, 需要去掉 } }, '/api': { target: envConfig[process.env.mode].BASE_API, // 请求本地需要后台项目 ws: false, changeOrigin: true, pathRewrite: { '/api': '' // 默认所有请求都加了 api 前缀, 需要去掉 } } } }, parallel: os.cpus().length > 1, // 如果你不需要生产环境的 source map, 可以将其设置为 false 以加速生产环境构建. productionSourceMap: false, lintOnSave: false, // babel-loader no-ignore node_modules/* transpileDependencies: ['vue-plyr'] } module.exports = vueConfig
请问相关require文件能发一下吗谢谢
@shuperry 谢谢
plugins/theme.plugin? 在哪里 谢谢
大佬 env.config 也发下啊
@wyyina plugins/theme.plugin.js
const ThemeColorReplacer = require('webpack-theme-color-replacer')
const generate = require('@ant-design/colors/lib/generate').default
const getAntdSerials = (color) => {
// 淡化(即less的tint)
const lightens = new Array(9).fill().map((t, i) => {
return ThemeColorReplacer.varyColor.lighten(color, i / 10)
})
const colorPalettes = generate(color)
const rgb = ThemeColorReplacer.varyColor.toNum3(color.replace('#', '')).join(',')
return lightens.concat(colorPalettes).concat(rgb)
}
const themePluginOption = {
fileName: 'css/theme-colors-[contenthash:8].css',
matchColors: getAntdSerials('#1890ff'), // 主色系列
// 改变样式选择器,解决样式覆盖问题
changeSelector (selector) {
switch (selector) {
case '.ant-calendar-today .ant-calendar-date':
return ':not(.ant-calendar-selected-date):not(.ant-calendar-selected-day)' + selector
case '.ant-btn:focus,.ant-btn:hover':
return '.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger)'
case '.ant-btn.active,.ant-btn:active':
return '.ant-btn.active:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:active:not(.ant-btn-primary):not(.ant-btn-danger)'
case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':
case '.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon':
return ':not(.ant-steps-item-process)' + selector
// fixed https://github.com/vueComponent/ant-design-vue-pro/issues/876
case '.ant-steps-item-process .ant-steps-item-icon':
return ':not(.ant-steps-item-custom)' + selector
case '.ant-menu-horizontal>.ant-menu-item-active,.ant-menu-horizontal>.ant-menu-item-open,.ant-menu-horizontal>.ant-menu-item-selected,.ant-menu-horizontal>.ant-menu-item:hover,.ant-menu-horizontal>.ant-menu-submenu-active,.ant-menu-horizontal>.ant-menu-submenu-open,.ant-menu-horizontal>.ant-menu-submenu-selected,.ant-menu-horizontal>.ant-menu-submenu:hover':
case '.ant-menu-horizontal > .ant-menu-item-active,.ant-menu-horizontal > .ant-menu-item-open,.ant-menu-horizontal > .ant-menu-item-selected,.ant-menu-horizontal > .ant-menu-item:hover,.ant-menu-horizontal > .ant-menu-submenu-active,.ant-menu-horizontal > .ant-menu-submenu-open,.ant-menu-horizontal > .ant-menu-submenu-selected,.ant-menu-horizontal > .ant-menu-submenu:hover':
return '.ant-menu-horizontal > .ant-menu-item-active,.ant-menu-horizontal > .ant-menu-item-open,.ant-menu-horizontal > .ant-menu-item-selected,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-item:hover,.ant-menu-horizontal > .ant-menu-submenu-active,.ant-menu-horizontal > .ant-menu-submenu-open,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu-selected,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu:hover'
case '.ant-menu-horizontal > .ant-menu-item-selected > a':
case '.ant-menu-horizontal>.ant-menu-item-selected>a':
return '.ant-menu-horizontal:not(ant-menu-light):not(.ant-menu-dark) > .ant-menu-item-selected > a'
case '.ant-menu-horizontal > .ant-menu-item > a:hover':
case '.ant-menu-horizontal>.ant-menu-item>a:hover':
return '.ant-menu-horizontal:not(ant-menu-light):not(.ant-menu-dark) > .ant-menu-item > a:hover'
default :
return selector
}
}
}
const createThemeColorReplacerPlugin = () => new ThemeColorReplacer(themePluginOption)
module.exports = createThemeColorReplacerPlugin
env.config.js
module.exports = {
local: {
BASE_API: 'xxx'
},
dev: {
BASE_API: 'xxx'
},
sit: {
BASE_API: 'xxx'
},
prod: {
BASE_API: 'xxx',
}
}
package.json -> scripts
"scripts": {
"start": "cross-env mode=local vue-cli-service serve --open --mode local",
"build:dev": "cross-env mode=dev vue-cli-service build",
"build:sit": "cross-env mode=sit vue-cli-service build",
"build:prod": "cross-env mode=prod vue-cli-service build"
}
访问速度很慢 #943
我也开启了GZIP,原来6M,后来2M,但是首次加载30秒??? 还有其他方式吗
第一次就是慢点,等vue3出来,会显著改善
vue3也没快多少
vue3也没快多少
是的,没有感觉到vue3快过
部署之后比vue2现住快很多,开发环境的确不如vue2
It's really too slow.too slow...
nginx.conf 的 http 中加入 # gzip config片断
具体参数:
参考:在部署的时候开启nginx的gzip自己调节参数,以及history的try_files解决方案和相关https安全部署方案。