一个移动端项目的工程化部署总结

多环境部署

@vue/cli-service 安装了一个名为 vue-cli-service 的命令。你可以在 npm scripts 中以vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。

npm run serve启动本地开发环境。

在项目根目录中新建env.*可以设置环境变量。

变量我们统一在 src/config/env.*.js 里进行管理。

config下新建对应的文件进行管理的目的是修改起来方便,不需 要重启项目,符合开发习惯。

解决1px问题:vw布局

安装postcss-px-to-viewport;
新建.postcssrc.js文件,参考文档进行配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = {
plugins: {
autoprefixer: {
overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8']
},
'postcss-px-to-viewport': {
unitToConvert: "px", // 要转化的单位
viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度
unitPrecision: 6, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
propList: ["*"], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
fontViewportUnit: "vw", // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ['.ignore', '.hairlines'], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false, // 是否在媒体查询的css代码中也进行转换,默认false
exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
}
}
}

Sass全局样式

安装node-sass和sass-loader。
参考vue-cli官网针对css的配置文档,把全局的scss文件注入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
const defaultSettings = require('./src/config/index.js')
module.exports = {
css: {
extract: IS_PROD,
sourceMap: false,
loaderOptions: {
scss: {
additionalData: `
@import "assets/css/mixin.scss";
@import "assets/css/variables.scss";
`,
},
},
},
}

移动端组件库

选择了有赞出品的vant,按需引入参考官网文档。

为了避免每个页面都还要import组件的写法,最好是在一个文件里统一做引入,挂载全局,这样任何组件都可以直接用了。
可以在 src/plugins/vant.js 下统一管理。

vant主题定制

首先安装sass-loader和sass包。
babel.config.js的plugins里做修改:

1
2
3
4
5
6
7
const plugins = [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: (name) => `${name}/style/less`,
}, 'vant']
];

最后在vue.config.js里加入lessOptions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module.exports = {
css: {
loaderOptions: {
less: {
// 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
lessOptions: {
modifyVars: {
// 直接覆盖变量
'text-color': '#111',
'border-color': '#eee',
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
hack: `true; @import "your-less-file-path.less";`,
},
},
},
},
},
};

注意,如果选择直接覆盖变量,修改以后需要重启服务。
鉴于要修改的主题太多,全写在配置文件里看着很难受,所以我用hack引入文件,看着比较舒服,而且不需要重启服务,一举两得。
样式修改的主题就参考vant文档每一个组件下边的列表即可。

打包分析

使用webpack-bundle-analyzer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
chainWebpack: config => {
// 打包分析
if (IS_PROD) {
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
{
analyzerMode: 'static'
}
])
}
}
}

去掉console.log

因为开发过程中经常需要打印一些值来调试,但是生产环境的版本不应该打印出来。又不想一点一点删除,所以需要一个工具自动删除线上环境的console。
使用babel-plugin-transform-remove-console
在 babel.config.js 中配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 获取 VUE_APP_ENV 非 NODE_ENV,测试环境依然 console
const IS_PROD = ['production', 'prod'].includes(process.env.VUE_APP_ENV)
const plugins = [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
style: true
},
'vant'
]
]
// 去除 console.log
if (IS_PROD) {
plugins.push('transform-remove-console')
}
module.exports = {
presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]],
plugins
}

splitChunks 单独打包第三方模块

使用script-ext-html-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
35
36
37
38
39
40
41
module.exports = {
chainWebpack: config => {
config.when(IS_PROD, config => {
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [
{
// 将 runtime 作为内联引入不单独存在
inline: /runtime\..*\.js$/
}
])
.end()
config.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
// cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块
commons: {
name: 'chunk-commons',
test: resolve('src/components'),
minChunks: 3, // 被至少用三次以上打包分离
priority: 5, // 优先级
reuseExistingChunk: true // 表示是否使用已有的 chunk,如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。
},
node_vendors: {
name: 'chunk-libs',
chunks: 'initial', // 只打包初始时依赖的第三方
test: /[\\/]node_modules[\\/]/,
priority: 10
},
vantUI: {
name: 'chunk-vantUI', // 单独将 vantUI 拆包
priority: 20, // 数字大权重到,满足多个 cacheGroups 的条件时候分到权重高的
test: /[\\/]node_modules[\\/]_?vant(.*)/
}
}
})
config.optimization.runtimeChunk('single')
})
}
}

Snapline wechat
扫码关注我的公众号“约翰柠檬的唱片店”
Buy me a cup of Coffee