赞
踩
默认是将这些都打包到vendor文件中,拆分后打包vendor会小很多
看一些文章里面写的’vue-router’: ‘Router’,发现不能用,必须得写成’vue-router’: ‘VueRouter’,
同理qs: ‘Qs’,后面的Qs也得用大写的,小写qs报错
chainWebpack: config => {
// 因为项目需要history/hash两种模式下打包,history模式才使用cdn引用,因此加了isHistory判断
// const isHistory = process.env.VUE_APP_ROUTER === 'history'
config.when(isHistory && (process.env.NODE_ENV === 'production'), config => {
// 使用externals设置排除项
config.set('externals', {
vue: 'Vue',
'vue-router': 'VueRouter',
axios: 'axios',
vuex: 'Vuex',
qs: 'Qs'
})
})
}
如main.js中
// import Vue from 'vue'
router/index.js
// import Vue from 'vue'
// import VueRouter from 'vue-router'
import web from './web'
Vue.use(VueRouter) // 注意这里要使用VueRouter Vue.use不能去掉
// ....
fetch.js 注释掉import axios from ‘axios’ 和 import qs from ‘qs’;,并且引用时将qs改为Qs
// import axios from 'axios' // import qs from 'qs'; // 创建axios实例,请求超时时间10秒 const SERVICE = axios.create({ timeout: 20000 }); // 拦截器 SERVICE.interceptors.request.use( (config) => { if (config.method === 'post') { if(jsonStr.indexOf(config.data.action)>-1){ config.data = config.data.data; } else{ config.data = Qs.stringify(config.data.data); // 将qs改为Qs } } config.headers.common['ClientType'] = process.env.VUE_APP_ROUTER === 'history' ? 'web' : 'app' return config; }, (error) => { return Promise.reject(error); } );
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=Zgvao4zZE6L1DYqiGocXjkSSULStabdQ" ></script> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="stylesheet" name="theme" href=""> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/2.8.1/vue-router.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.6.2/vuex.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/qs/6.9.4/qs.min.js"></script> <title>title</title> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
通过webpack的tree shaking,未使用模块检测能力。新的 webpack 4 正式版本扩展了此检测能力。
webpack文档:tree shaking
如果项目没有影响,可以直接设置:“sideEffects”: false, 但修改后发现页面样式受影响了
文档中提到应该将css文件排除检测,于是改为:
"sideEffects": ["*.css"],
但是我自己写的公用样式还是没加载进来,发现是.styl格式的,于是再加入
"sideEffects": ["*.css", "*.styl"],
但是.vue页面中写的样式还是没出现,于是:
"sideEffects": ["*.css", "*.styl", "*.vue"]
这样,样式就可以正常显示了
后来测试发现,有部分js也受影响了
因为在main.js中这样引入了validator和draggable,但是打包时被扔掉了
import '@/validator'
import '@/draggable'
因此需要将其排除
"sideEffects": ["*.css", "*.styl", "*.vue", "src/validator/index.js", "src/draggable/index.js"],
"scripts": {
// ...
"serve": "vue-cli-service serve",
"inspect": "vue inspect > webpack.js"
}
config.plugin('webpack-bundle-analyzer').use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
完整vue.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') .BundleAnalyzerPlugin // 代码压缩 // const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const path = require('path') // const resolve = file => path.resolve(__dirname, file) const poststylus = require('poststylus') const pxtorem = require('postcss-pxtorem') const IS_PRO = ['production', 'test'].includes(process.env.NODE_ENV) // const path = require('path') // function resolve(dir) { // return path.join(__dirname, dir) // } const isHistory = process.env.VUE_APP_ROUTER === 'history' const masterPage = { login: { entry: 'src/login/login.js', template: 'public/login.html', chunks: ['vendors', 'vue', 'vuex', 'vue-router', 'login'] }, index: { entry: 'src/main.js', template: 'public/indexApp.html', chunks: ['vendors', 'vue', 'vuex', 'vue-router', 'echarts', 'index'] } } const xjPage = { index: { entry: 'src/main.history.js', template: 'public/index.html', chunks: ['chunk-vendors', 'chunk-common', 'index'] } } const baseUrl = '/' module.exports = { publicPath: isHistory ? '/xj/' : './', outputDir: isHistory ? 'xj' : 'master', assetsDir: 'static', lintOnSave: true, pages: isHistory ? xjPage : masterPage, transpileDependencies: [ 'mand-mobile' ], productionSourceMap: false, chainWebpack: config => { config.optimization.usedExports = true config.when(isHistory && (process.env.NODE_ENV === 'production'), config => { // 使用externals设置排除项 config.set('externals', { vue: 'Vue', 'vue-router': 'VueRouter', axios: 'axios', vuex: 'Vuex', qs: 'Qs' }) }) config.module.rule('eslint') config.module.rule('eslint').use('eslint-loader') config.resolve.alias .set('@', path.join(__dirname, 'src')) config.module.rule('styl') .test('/\.styl$/') .use('css-loader') .loader('stylus-loader') .end() config.module.rule('images') .use('url-loader') .loader('url-loader') .tap(options => Object.assign(options, { limit: 2048 })) if (process.env.NODE_ENV === 'production') { config.plugin('optimize-css').tap(([{ cssnanoOptions, ...args }]) => { const preset = cssnanoOptions.preset || [] preset.forEach(item => { if (typeof item === 'object') { item.calc = false } }) cssnanoOptions.preset = preset return [{ cssnanoOptions, ...args }] }) } // config.plugin('webpack-bundle-analyzer').use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin) }, css: { extract: IS_PRO, sourceMap: false, requireModuleExtension: true, loaderOptions: { stylus: { use: [ poststylus([ pxtorem({ rootValue: 100, propWhiteList: [] }), 'autoprefixer' ]) ] // import: [ // resolve('./src/assets/theme.custom') // ] }, postcss: { plugins: [ require('postcss-pxtorem')({ rootValue: 100, propWhiteList: [], minPixelValue: 2 }), require('autoprefixer')() ] } } }, parallel: require('os').cpus().length > 1, pwa: {}, devServer: { host: '0.0.0.0', port: 8889, https: false, hotOnly: false, open: true, before: function(app) { const base = baseUrl.replace(/\/+$/, '') // 移除尾部斜杠 app.get(`${base}/:page/*`, function(req, res, next) { if (['login', 'index'].includes(req.params.page)) { // 把 /<base>/<page>/* 重定向到 /<base>/<page>/ req.url = `${base}/${req.params.page}/` next('route') } else { next() } }) } }, configureWebpack: config => { if (!isHistory) { config.optimization = { splitChunks: { chunks: 'all', maxInitialRequests: 6, cacheGroups: { vue: { name: 'vue', test: /[\\/]node_modules[\\/]vue[\\/]/, priority: -10 }, vuex: { name: 'vuex', test: /[\\/]node_modules[\\/]vuex[\\/]/, priority: -10 }, 'vue-router': { name: 'vue-router', test: /[\\/]node_modules[\\/]vue-router[\\/]/, priority: -10 }, 'echarts': { name: 'echarts', test: /[\\/]node_modules[\\/]echarts[\\/]/, priority: -10 }, 'vendors': { name: 'vendors', test: /[\\/]node_modules[\\/]/, priority: -20 } } } } } if (process.env.NODE_ENV === 'production') { } else { // 为开发环境修改配置... config.devtool = 'source-map' } }, pluginOptions: {} }
针对hash模式下的多页面(登录页、登录后页),进行优化,登录页只用到了几个登录、注册,因此无需引用echarts,所以将echarts单独打包,配置:
config.optimization 中的 splitChunks,如上代码:
const masterPage = {
login: {
entry: 'src/login/login.js',
template: 'public/login.html',
chunks: ['vendors', 'vue', 'vuex', 'vue-router', 'login']
},
index: {
entry: 'src/main.js',
template: 'public/indexApp.html',
chunks: ['vendors', 'vue', 'vuex', 'vue-router', 'echarts', 'index']
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。