feat: 提供多页面构建示例,优化了打包分包,取消CDN加载依赖但保留了设置入口

This commit is contained in:
FairyEver
2020-12-03 22:03:58 +08:00
parent a947e40e14
commit 41a7e02eb5
15 changed files with 411 additions and 98 deletions

View File

@@ -2,49 +2,97 @@ const CompressionWebpackPlugin = require('compression-webpack-plugin')
const VueFilenameInjector = require('@d2-projects/vue-filename-injector')
const ThemeColorReplacer = require('webpack-theme-color-replacer')
const forElementUI = require('webpack-theme-color-replacer/forElementUI')
const cdnDependencies = require('./dependencies-cdn')
const { chain, set, each } = require('lodash')
const { set, each, compact, map, keys } = require('lodash')
// 拼接路径
const resolve = dir => require('path').join(__dirname, dir)
// 增加环境变量
// Add environment variable
process.env.VUE_APP_VERSION = require('./package.json').version
process.env.VUE_APP_BUILD_TIME = require('dayjs')().format('YYYY-M-D HH:mm:ss')
// 基础路径 注意发布之前要先修改这里
const publicPath = process.env.VUE_APP_PUBLIC_PATH || '/'
// 设置不参与构建的库
const externals = {}
cdnDependencies.forEach(pkg => { externals[pkg.name] = pkg.library })
// 引入文件的 cdn 链接
const cdn = {
css: cdnDependencies.map(e => e.css).filter(e => e),
js: cdnDependencies.map(e => e.js).filter(e => e)
// Build configuration for multiple pages
const pages = {
index: {
entry: 'src/main.js',
template: 'public/index.html',
filename: 'index.html',
chunks: [
'manifest',
'index',
'chunk-index',
'chunk-vendor',
'chunk-common',
'chunk-vue',
'chunk-element'
]
},
mobile: {
entry: 'src.mobile/main.js',
template: 'public/mobile.html',
filename: 'mobile.html',
chunks: [
'manifest',
'mobile',
'chunk-mobile',
'chunk-vendor',
'chunk-common',
'chunk-vue'
]
}
}
// 多页配置,默认未开启,如需要请参考 https://cli.vuejs.org/zh/config/#pages
const pages = undefined
// const pages = {
// index: './src/main.js',
// subpage: './src/subpage.js'
// }
// Set up the external dependency package introduced by the method of using CDN
// For example
// if you set the Axios related link configuration here
// Axios will no longer participate in the packaging during the construction. Finally
// the external link you configured will be used to import Axios in the build result
const cdn = {
// Which external dependencies related to index page are introduced in the form of CDN links
index: [
// {
// name: 'axios',
// library: 'axios',
// js: 'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js',
// css: ''
// }
],
// Which external dependencies related to mobile page are introduced in the form of CDN links
mobile: [
// {
// name: 'axios',
// library: 'axios',
// js: 'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js',
// css: ''
// }
]
}
// Set external dependent packages that do not participate in the build
const externals = {}
keys(pages).forEach(name => {
cdn[name].forEach(p => {
externals[p.name] = p.library
})
})
module.exports = {
// 根据你的实际情况更改这里
publicPath,
publicPath: process.env.VUE_APP_PUBLIC_PATH || '/',
lintOnSave: true,
devServer: {
publicPath, // 和 publicPath 保持一致
disableHostCheck: process.env.NODE_ENV === 'development' // 关闭 host check方便使用 ngrok 之类的内网转发工具
publicPath: process.env.VUE_APP_PUBLIC_PATH || '/',
disableHostCheck: process.env.NODE_ENV === 'development'
},
css: {
loaderOptions: {
// 设置 scss 公用变量文件
sass: {
prependData: '@import \'~@/assets/style/public.scss\';'
},
less: {
lessOptions: {
modifyVars: {
blue: '#2262AB'
}
}
}
}
},
@@ -66,33 +114,92 @@ module.exports = {
}
return configNew
},
// 默认设置: https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-service/lib/config/base.js
// default: https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-service/lib/config/base.js
chainWebpack: config => {
/**
* 添加 CDN 参数到 htmlWebpackPlugin 配置中
* 已适配多页
*/
const htmlPluginNames = chain(pages).keys().map(page => 'html-' + page).value()
const targetHtmlPluginNames = htmlPluginNames.length ? htmlPluginNames : ['html']
each(targetHtmlPluginNames, name => {
config.plugin(name).tap(options => {
set(options, '[0].cdn', process.env.NODE_ENV === 'production' ? cdn : [])
config.optimization.runtimeChunk({
name: 'manifest'
})
config.optimization.splitChunks({
cacheGroups: {
// External dependencies common to all pages
libs: {
name: 'chunk-vendor',
chunks: 'initial',
minChunks: 1,
test: /[\\/]node_modules[\\/]/,
priority: 1,
reuseExistingChunk: true,
enforce: true
},
// Code common to all pages
common: {
name: 'chunk-common',
chunks: 'initial',
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
priority: 2,
reuseExistingChunk: true,
enforce: true
},
// External dependencies that are only used by the index page
index: {
name: 'chunk-index',
chunks: 'all',
minChunks: 1,
test: /[\\/]node_modules[\\/](sortablejs|screenfull|nprogress|hotkeys-js|fuse\.js|better-scroll|lowdb|shortid)[\\/]/,
priority: 3,
reuseExistingChunk: true,
enforce: true
},
// External dependencies that are only used by the mobile page
mobile: {
name: 'chunk-mobile',
chunks: 'all',
minChunks: 1,
test: /[\\/]node_modules[\\/](vant)[\\/]/,
priority: 3,
reuseExistingChunk: true,
enforce: true
},
// Vue family packages
vue: {
name: 'chunk-vue',
test: /[\\/]node_modules[\\/](vue|vue-router|vuex)[\\/]/,
chunks: 'all',
priority: 3,
reuseExistingChunk: true,
enforce: true
},
// only element-ui
element: {
name: 'chunk-element',
test: /[\\/]node_modules[\\/]element-ui[\\/]/,
chunks: 'all',
priority: 3,
reuseExistingChunk: true,
enforce: true
}
}
})
// Add the CDN settings to the settings of the htmlwebpackplugin plug-in
keys(pages).forEach(name => {
const packages = cdn[name]
config.plugin(`html-${name}`).tap(options => {
const setting = {
css: compact(map(packages, 'css')),
js: compact(map(packages, 'js'))
}
set(options, '[0].cdn', process.env.NODE_ENV === 'production' ? setting : [])
return options
})
})
/**
* 删除懒加载模块的 prefetch preload降低带宽压力
* https://cli.vuejs.org/zh/guide/html-and-static-assets.html#prefetch
* https://cli.vuejs.org/zh/guide/html-and-static-assets.html#preload
* 而且预渲染时生成的 prefetch 标签是 modern 版本的,低版本浏览器是不需要的
*/
config.plugins
.delete('prefetch')
.delete('preload')
// 解决 cli3 热更新失效 https://github.com/vuejs/vue-cli/issues/1559
config.resolve
.symlinks(true)
// Remove prefetch preload settings for lazy load modules
each(keys(pages), name => {
config.plugins.delete(`prefetch-${name}`)
config.plugins.delete(`preload-${name}`)
})
// webpack-theme-color-replacer
config
.plugin('theme-color-replacer')
.use(ThemeColorReplacer, [{
@@ -104,11 +211,11 @@ module.exports = {
changeSelector: forElementUI.changeSelector
}])
config
// 开发环境 sourcemap 不包含列信息
// The development environment sourcemap does not contain column information
.when(process.env.NODE_ENV === 'development',
config => config.devtool('cheap-source-map')
)
// 预览环境构建 vue-loader 添加 filename
// Add file name
.when(
process.env.VUE_APP_SCOURCE_LINK === 'TRUE',
config => VueFilenameInjector(config, {
@@ -142,15 +249,9 @@ module.exports = {
.exclude
.add(resolve('src/assets/svg-icons/icons'))
.end()
// 重新设置 alias
// set alias
config.resolve.alias
.set('@api', resolve('src/api'))
// 分析工具
if (process.env.npm_config_report) {
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
}
.set('@.mobile', resolve('src.mobile'))
},
// 不输出 map 文件
productionSourceMap: false,