Vue-cli3通用多页面脚手架

目前 vue-cli3 生成的配置是做单页面的,然而,我们有时也会有多页面的需求 。比如我们最常见的一个项目跑多个独立的小型的H5页面,这些页面不可能每一次都开一个新项目.但是在实际的项目中,我们需要这样的脚手架,参考了很多大牛的脚手架,这里提供了一种我的单页面脚手架转换为多页面脚手架的方案,供大家参考。

要求:

  • 1.首页显示项目所有的H5链接列表;
  • 2.支持小型本地收据mock,方便本地测试接口【我个人不推荐,建议mock和项目分离】

准备

使用vue-cli生成一个你需要的单页面项目脚手架,然后我们就可以为所欲为了,目录我就不说明了,默认大家都知道。

每一次新开的页面都在pages里面起一个文件夹,文件夹名字就是H5页面名字,入口文件是文件夹的index.html和index.js

修改vue.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
let path = require('path')
let glob = require('glob')
let mock = require('./src/mock/index.json');
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
//配置pages多页面获取当前文件夹下的html和js
function getEntry(globPath) {
let entries = {};
glob.sync(globPath).forEach(function(entry) {
var tmp = entry.split('/').splice(-3);
entries[tmp[1]] = {
entry: 'src/' + tmp[0] + '/' + tmp[1] + '/' + 'index.js',
template: 'src/' + tmp[0] + '/' + tmp[1] + '/' + 'index.html',
filename: tmp[1]
};
});
return entries;
}

let pages = getEntry('./src/pages/**?/*.html');

module.exports = {
lintOnSave: false,
baseUrl: process.env.NODE_ENV === "production" ? 'https://www.baidu.com/' : '/',
productionSourceMap: false,
pages,
devServer: {
index: '/',
open: process.platform === 'darwin',
host: '',
port: 9527,
https: false,
hotOnly: false,
proxy: {
'/xrf/': {
target: 'http://reg.tool.hexun.com/',
changeOrigin: true,
pathRewrite: {
'^/xrf': ''
}
},
}, // 设置代理
before: app => {
app.get('/', (req, res, next) => {
for(let i in pages){
res.write(`<a target="_self" href="/${i}">/${i}</a></br>`);
}
res.end()
});
app.get('/goods/list', (req, res, next) => { //mock数据
res.status(299).json(mock)
})
}
},
chainWebpack: config => {
config.module
.rule('images')
.use('url-loader')
.loader('url-loader')
.tap(options => {
// 修改它的选项...
options.limit = 100
return options
})
Object.keys(pages).forEach(entryName => {
config.plugins.delete(`prefetch-${entryName}`);
});
if(process.env.NODE_ENV === "production") {
config.plugin("extract-css").tap(() => [{
path: path.join(__dirname, "./dist"),
filename: "css/[name].[contenthash:8].css"
}]);
}
},
configureWebpack: config => {
// if(process.env.NODE_ENV === "production") {
// config.output = {
// path: path.join(__dirname, "./dist"),
// filename: "js/[name].[contenthash:8].js"
// };
// }
}
}

启动项目,显示项目所有H5连接

最主要的是修改:

before第一个参数express实例。

1
2
3
4
5
6
7
8
9
10
11
before: app => {     
app.get('/', (req, res, next) => {
for(let i in pages){ //遍历项目链接
res.write(`<a target="_self" href="/${i}">/${i}</a></br>`);
}
res.end()
});
app.get('/goods/list', (req, res, next) => { //mock数据
res.status(299).json(mock)
})
}

拦截器

【vue-cli3升级】老项目提速50%(二)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import store from '@/store'
import axios from 'axios'
import { Toast } from 'vant'
import util from '@/libs/util'

// 创建一个错误
const errorCreate = msg => {
const err = new Error(msg)
errorLog(err)
throw err
}

// 记录和显示错误
const errorLog = err => {
// 添加到日志
store.dispatch('xxx/log/add', {
type: 'error',
err,
info: '数据请求异常'
})
// 打印到控制台
if (process.env.NODE_ENV === 'development') {
util.log.danger('>>>>>> Error >>>>>>')
console.log(err)
}
// 显示提示
Toast({
message: err.message,
type: 'error'
})
}

// 创建一个 axios 实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000 // 请求超时时间
})

// 请求拦截器
service.interceptors.request.use(
config => {
// 在请求发送之前做一些处理
const token = util.cookies.get('token')
config.headers['X-Token'] = token
// 处理mock
if (process.env.VUE_APP_MOCK && config.isMock) {
config.url = `${process.env.VUE_APP_MOCK_BASE_URL}/${config.url}`
}
return config
},
error => {
// 发送失败
console.log(error)
Promise.reject(error)
}
)

// 响应拦截器
service.interceptors.response.use(
response => {
const dataAxios = response.data
const { code } = dataAxios
if (!code) return dataAxios
switch (code) {
case 0:
case 10000:
// 成功
return dataAxios.data
case 'xxx':
errorCreate(`[ code: xxx ] ${dataAxios.msg}: ${response.config.url}`)
break
default:
// 不是正确的 code
errorCreate(`${dataAxios.msg}: ${response.config.url}`)
break
}
},
error => {
if (error && error.response) {
switch (error.response.status) {
case 400: error.message = '请求错误'; break
case 401: error.message = '未授权,请登录'; break
case 403: error.message = '拒绝访问'; break
case 404: error.message = `请求地址出错: ${error.response.config.url}`; break
case 408: error.message = '请求超时'; break
case 500: error.message = '服务器内部错误'; break
case 501: error.message = '服务未实现'; break
case 502: error.message = '网关错误'; break
case 503: error.message = '服务不可用'; break
case 504: error.message = '网关超时'; break
case 505: error.message = 'HTTP版本不受支持'; break
default: break
}
}
errorLog(error)
return Promise.reject(error)
}
)
export default service


vue-cli3 全面配置(持续更新)

目录

☞ 配置多环境变量

  通过在 package.json 里的 scripts 配置项中添加–mode xxx 来选择不同环境

  在项目根目录中新建.env, .env.production, .env.analyz 等文件

  只有以 VUEAPP 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中,代码中可以通过 process.env.VUE_APP_BASE_API 访问

  NODE_ENV 和 BASE_URL 是两个特殊变量,在代码中始终可用

.env serve 默认的环境变量
1
2
NODE_ENV = 'development'
VUE_APP_BASE_API = 'https://demo.cn/api'
.env.production build 默认的环境变量

  如果开启 ali oss,VUE_APP_SRC 配置为 ali oss 资源 url 前缀,如:’https://staven.oss-cn-hangzhou.aliyuncs.com/demo'

1
2
3
4
5
6
7
8
9
10
NODE_ENV = 'production'

VUE_APP_BASE_API = 'https://demo.com/api'
VUE_APP_SRC = '/'

ACCESS_KEY_ID = ''
ACCESS_KEY_SECRET = ''
REGION = 'oss-cn-hangzhou'
BUCKET = 'staven'
PREFIX = 'demo'
.env.analyz 用于 webpack-bundle-analyzer 打包分析

  如果开启 ali oss,VUE_APP_SRC 配置为 ali oss 资源 url 前缀,如:’https://staven.oss-cn-hangzhou.aliyuncs.com/demo'

1
2
3
4
5
6
7
8
9
10
11
NODE_ENV = 'production'
IS_ANALYZ = 'analyz'

VUE_APP_BASE_API = 'https://demo.com/api'
VUE_APP_SRC = '/'

ACCESS_KEY_ID = ''
ACCESS_KEY_SECRET = ''
REGION = 'oss-cn-hangzhou'
BUCKET = 'staven'
PREFIX = 'demo'

  修改 package.json

1
2
3
4
5
6
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"analyz": "vue-cli-service build --mode analyz",
"lint": "vue-cli-service lint"
}

▲ 回顶部

☞ 配置基础 vue.config.js

1
2
3
4
5
6
7
8
9
10
11
12
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV);

module.exports = {
baseUrl: './', // 默认'/',部署应用包时的基本 URL
outputDir: process.env.outputDir || 'dist', // 'dist', 生产环境构建文件的目录
assetsDir: '', // 相对于outputDir的静态资源(js、css、img、fonts)目录
lintOnSave: false,
runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
productionSourceMap: false, // 生产环境的 source map
parallel: require('os').cpus().length > 1,
pwa: {}
};

▲ 回顶部

☞ 配置 proxy 跨域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV);
module.exports = {
devServer: {
// overlay: {
// warnings: true,
// errors: true
// },
open: IS_PROD,
host: '0.0.0.0',
port: 8000,
https: false,
hotOnly: false,
proxy: {
'/api': {
target: process.env.VUE_APP_BASE_API || 'http://127.0.0.1:8080',
changeOrigin: true
}
}
}
}

▲ 回顶部

☞ 修复 HMR(热更新)失效

1
2
3
4
5
6
module.exports = {
chainWebpack: config => {
// 修复HMR
config.resolve.symlinks(true);
}
}

▲ 回顶部

☞ 修复 Lazy loading routes Error: Cyclic dependency https://github.com/vuejs/vue-cli/issues/1669

1
2
3
4
5
6
7
8
module.exports = {
chainWebpack: config => {
config.plugin('html').tap(args => {
args[0].chunksSortMode = 'none';
return args;
});
}
}

▲ 回顶部

☞ 添加别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const path =  require('path');
const resolve = (dir) => path.join(__dirname, dir);
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV);

module.exports = {
chainWebpack: config => {
// 添加别名
config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('components', resolve('src/components'))
.set('layout', resolve('src/layout'))
.set('base', resolve('src/base'))
.set('static', resolve('src/static'));
}
}

▲ 回顶部

☞ 去除多余无效的 css

1
npm i --save-dev glob-all purgecss-webpack-plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const PurgecssPlugin = require('purgecss-webpack-plugin');
const glob = require('glob-all');
const path = require('path')

module.exports = {
configureWebpack: config => {
if (IS_PROD) {
const plugins = [];
plugins.push(
new PurgecssPlugin({
paths: glob.sync([
path.join(__dirname, './src/index.html'),
path.join(__dirname, './**/*.vue'),
path.join(__dirname, './src/**/*.js')
])
})
);
config.plugins = [
...config.plugins,
...plugins
];
}
}
}

▲ 回顶部

☞ 添加打包分析

1
2
3
4
5
6
7
8
9
10
11
12
13
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
chainWebpack: config => {
// 打包分析
if (process.env.IS_ANALYZ) {
config.plugin('webpack-report')
.use(BundleAnalyzerPlugin, [{
analyzerMode: 'static',
}]);
}
}
}

▲ 回顶部

☞ 配置 externals

  防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖

1
2
3
4
5
6
7
8
9
10
11
12

module.exports = {
configureWebpack: config => {
config.externals = {
'vue': 'Vue',
'element-ui': 'ELEMENT',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios'
}
}
}

▲ 回顶部

☞ 去掉 console.log

方法一:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
configureWebpack: config => {
if (IS_PROD) {
const plugins = [];
plugins.push(
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
drop_console: true,
drop_debugger: false,
pure_funcs: ['console.log']//移除console
}
},
sourceMap: false,
parallel: true
})
);
config.plugins = [
...config.plugins,
...plugins
];
}
}
}
方法二:使用 babel-plugin-transform-remove-console 插件
1
npm i --save-dev babel-plugin-transform-remove-console

在 babel.config.js 中配置

1
2
3
4
5
6
7
8
9
const plugins = [];
if(['production', 'prod'].includes(process.env.NODE_ENV)) {
plugins.push("transform-remove-console")
}

module.exports = {
presets: [["@vue/app",{"useBuiltIns": "entry"}]],
plugins: plugins
};

▲ 回顶部

☞ 开启 gzip 压缩

1
npm i --save-dev compression-webpack-plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;

module.exports = {
configureWebpack: config => {
if (IS_PROD) {
const plugins = [];
plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8
})
);
config.plugins = [
...config.plugins,
...plugins
];
}
}
}

  还可以开启比 gzip 体验更好的 Zopfli 压缩详见https://webpack.js.org/plugins/compression-webpack-plugin

1
npm i --save-dev @gfx/zopfli brotli-webpack-plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const zopfli = require("@gfx/zopfli");
const BrotliPlugin = require("brotli-webpack-plugin");
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;

module.exports = {
configureWebpack: config => {
if (IS_PROD) {
const plugins = [];
plugins.push(
new CompressionWebpackPlugin({
algorithm(input, compressionOptions, callback) {
return zopfli.gzip(input, compressionOptions, callback);
},
compressionOptions: {
numiterations: 15
},
minRatio: 0.99,
test: productionGzipExtensions
})
);
plugins.push(
new BrotliPlugin({
test: productionGzipExtensions,
minRatio: 0.99
})
);
config.plugins = [
...config.plugins,
...plugins
];
}
}
}

▲ 回顶部

☞ 为 sass 提供全局样式,以及全局变量

  可以通过在 main.js 中 Vue.prototype.$src = process.env.VUE_APP_SRC;挂载环境变量中的配置信息,然后在js中使用$src 访问。

  css 中可以使用注入 sass 变量访问环境变量中的配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
css: {
modules: false,
extract: IS_PROD,
sourceMap: false,
loaderOptions: {
sass: {
// 向全局sass样式传入共享的全局变量
data: `@import "~assets/scss/variables.scss";$src: "${process.env.VUE_APP_SRC}";`
}
}
}
}

在 scss 中引用

1
2
3
.home {
background: url($src + '/images/500.png');
}

▲ 回顶部

☞ 添加 IE 兼容

1
npm i --save @babel/polyfill

  在 main.js 中添加

1
import '@babel/polyfill';

配置 babel.config.js

1
2
3
4
5
6
const plugins = [];

module.exports = {
presets: [["@vue/app",{"useBuiltIns": "entry"}]],
plugins: plugins
};

▲ 回顶部

☞ 文件上传 ali oss

  开启文件上传 ali oss,需要将 baseUrl 改成 ali oss 资源 url 前缀,也就是修改 VUE_APP_SRC

1
npm i --save-dev webpack-oss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const AliOssPlugin = require('webpack-oss');

module.exports = {
configureWebpack: config => {
if (IS_PROD) {
const plugins = [];
// 上传文件到oss
if (process.env.ACCESS_KEY_ID || process.env.ACCESS_KEY_SECRET || process.env.REGION || process.env.BUCKET || process.env.PREFIX) {
plugins.push(
new AliOssPlugin({
accessKeyId: process.env.ACCESS_KEY_ID,
accessKeySecret: process.env.ACCESS_KEY_SECRET,
region: process.env.REGION,
bucket: process.env.BUCKET,
prefix: process.env.PREFIX,
exclude: /.*\.html$/,
deleteAll: false
})
);
}
config.plugins = [
...config.plugins,
...plugins
];
}
}
}

▲ 回顶部

☞ 完整配置

  • 安装依赖
1
npm i --save-dev compression-webpack-plugin babel-plugin-transform-remove-console  glob-all purgecss-webpack-plugin

  其他依赖(@gfx/zopfli、brotli-webpack-plugin、webpack-oss)根据需求选择安装

  • 环境配置

.env

1
2
NODE_ENV = 'development'
VUE_APP_BASE_API = 'https://demo.cn/api'

.env.production

  如果开启 ali oss,VUE_APP_SRC 配置为 ali oss 资源 url 前缀,如:’https://staven.oss-cn-hangzhou.aliyuncs.com/demo'

1
2
3
4
5
6
7
8
9
10
NODE_ENV = 'production'

VUE_APP_BASE_API = 'https://demo.com/api'
VUE_APP_SRC = '/'

ACCESS_KEY_ID = ''
ACCESS_KEY_SECRET = ''
REGION = 'oss-cn-hangzhou'
BUCKET = 'staven'
PREFIX = 'demo'

.env.analyz

  如果开启 ali oss,VUE_APP_SRC 配置为 ali oss 资源 url 前缀,如:’https://staven.oss-cn-hangzhou.aliyuncs.com/demo'

1
2
3
4
5
6
7
8
9
10
11
NODE_ENV = 'production'
IS_ANALYZ = 'analyz'

VUE_APP_BASE_API = 'https://demo.com/api'
VUE_APP_SRC = VUE_APP_SRC = '/'

ACCESS_KEY_ID = ''
ACCESS_KEY_SECRET = ''
REGION = 'oss-cn-hangzhou'
BUCKET = 'staven'
PREFIX = 'demo'
  • package.json
1
2
3
4
5
6
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"analyz": "vue-cli-service build --mode analyz",
"lint": "vue-cli-service lint"
}
  • babel.config.js
1
2
3
4
5
6
7
8
9
const plugins = [];
// if(['production', 'prod'].includes(process.env.NODE_ENV)) {
// plugins.push("transform-remove-console")
// }

module.exports = {
presets: [["@vue/app",{"useBuiltIns": "entry"}]],
plugins: plugins
};
  • vue.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const CompressionWebpackPlugin = require("compression-webpack-plugin");
// const zopfli = require("@gfx/zopfli");
// const BrotliPlugin = require("brotli-webpack-plugin");
const AliOssPlugin = require("webpack-oss");

const path = require("path");
const PurgecssPlugin = require("purgecss-webpack-plugin");
const glob = require("glob-all");

const resolve = dir => path.join(__dirname, dir);
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;

module.exports = {
baseUrl: IS_PROD ? process.env.VUE_APP_SRC || "/" : "./", // 默认'/',部署应用包时的基本 URL
outputDir: process.env.outputDir || "dist", // 'dist', 生产环境构建文件的目录
assetsDir: "", // 相对于outputDir的静态资源(js、css、img、fonts)目录
lintOnSave: false,
runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
productionSourceMap: false, // 生产环境的 source map

configureWebpack: config => {
// cdn引用时配置externals
// config.externals = {
// 'vue': 'Vue',
// 'element-ui': 'ELEMENT',
// 'vue-router': 'VueRouter',
// 'vuex': 'Vuex',
// 'axios': 'axios'
// }

if (IS_PROD) {
const plugins = [];

plugins.push(
new PurgecssPlugin({
paths: glob.sync([
path.join(__dirname, "./src/index.html"),
path.join(__dirname, "./**/*.vue"),
path.join(__dirname, "./src/**/*.js")
])
})
);

plugins.push(
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
drop_console: true,
drop_debugger: false,
pure_funcs: ["console.log"] //移除console
}
},
sourceMap: false,
parallel: true
})
);
plugins.push(
new CompressionWebpackPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8
})
);

// 上传文件到oss
//if (process.env.ACCESS_KEY_ID || process.env.ACCESS_KEY_SECRET || process.env.REGION || process.env.BUCKET || process.env.PREFIX) {
// plugins.push(
// new AliOssPlugin({
// accessKeyId: process.env.ACCESS_KEY_ID,
// accessKeySecret: process.env.ACCESS_KEY_SECRET,
// region: process.env.REGION,
// bucket: process.env.BUCKET,
// prefix: process.env.PREFIX,
// exclude: /.*\.html$/,
// deleteAll: false
// })
// );
//}

// Zopfli压缩,需要响应VC库 https://webpack.js.org/plugins/compression-webpack-plugin/
// plugins.push(
// new CompressionWebpackPlugin({
// algorithm(input, compressionOptions, callback) {
// return zopfli.gzip(input, compressionOptions, callback);
// },
// compressionOptions: {
// numiterations: 15
// },
// minRatio: 0.99,
// test: productionGzipExtensions
// })
// );
// plugins.push(
// new BrotliPlugin({
// test: productionGzipExtensions,
// minRatio: 0.99
// })
// );
config.plugins = [...config.plugins, ...plugins];
}
},
chainWebpack: config => {
// 修复HMR
config.resolve.symlinks(true);

// 修复Lazy loading routes Error: Cyclic dependency [https://github.com/vuejs/vue-cli/issues/1669]
config.plugin("html").tap(args => {
args[0].chunksSortMode = "none";
return args;
});

// 添加别名
config.resolve.alias
.set("@", resolve("src"))
.set("assets", resolve("src/assets"))
.set("components", resolve("src/components"))
.set("layout", resolve("src/layout"))
.set("base", resolve("src/base"))
.set("static", resolve("src/static"));

// 打包分析
if (process.env.IS_ANALYZ) {
config.plugin("webpack-report").use(BundleAnalyzerPlugin, [
{
analyzerMode: "static"
}
]);
}

// 多页面配置,为js添加hash
// config.output.chunkFilename(`js/[name].[chunkhash:8].js`)

// 修改图片输出路径
// config.module
// .rule('images')
// .test(/\.(png|jpe?g|gif|ico)(\?.*)?$/)
// .use('url-loader')
// .loader('url-loader')
// .options({
// name: path.join('../assets/', 'img/[name].[ext]')
// })
},
css: {
modules: false,
extract: IS_PROD,
// 为css后缀添加hash
// extract: {
// filename: 'css/[name].[hash:8].css',
// chunkFilename: 'css/[name].[hash:8].css'
//},
sourceMap: false,
loaderOptions: {
sass: {
// 向全局sass样式传入共享的全局变量
// data: `@import "~assets/scss/variables.scss";$src: "${process.env.VUE_APP_SRC}";`
data: `$src: "${process.env.VUE_APP_SRC}";`
}
// px转换为rem
// postcss: {
// plugins: [
// require('postcss-pxtorem')({
// rootValue : 1, // 换算的基数
// selectorBlackList : ['weui', 'el'], // 忽略转换正则匹配项
// propList : ['*']
// })
// ]
// }
}
},
pluginOptions: {
// 安装vue-cli-plugin-style-resources-loader插件
// 添加全局样式global.scss
// "style-resources-loader": {
// preProcessor: "scss",
// patterns: [
// resolve(__dirname, "./src/scss/scss/variables.scss")
// ]
// }
},
parallel: require("os").cpus().length > 1,
pwa: {},
devServer: {
// overlay: {
// warnings: true,
// errors: true
// },
open: IS_PROD,
host: "0.0.0.0",
port: 8000,
https: false,
hotOnly: false,
proxy: {
"/api": {
target: process.env.VUE_APP_BASE_API || "http://127.0.0.1:8080",
changeOrigin: true
}
}
}
};