升级背景
公司项目是用 vue-cli
搭建的,至今已经有2年了热更新也越来越慢,正好 vue cli3
也出来,听说编译速度大大提升,就想把项目移植到 vue cli3
现状
技术: "webpack": "^3.6.0", "vue": "^2.5.2"
- 代码量越来越大,编译速度也越来越慢,打包时间快一分钟,热更新也越来越慢,影响开发效率
- 没有引入
eslint
语法检查, 代码风格不一 webpack
配置繁琐- 越来越多的UI库支持vue cli3
升级目的
- 提升编译速度
- 在
vue cli3
创建项目时,引入eslint
,统一代码风格,方便代码review
(新手前端不想单独引入) - 所有配置
vue cli3
已经做了处理,额外配置在vue.config.js中处理即可 - 适应技术发展的潮流 🐶
项目升级
vue cl3 创建项目
vue create hello-world
详细步骤参考vue cli3文档
我用的配置是vue-router, vuex, less, babel, eslint
文件迁移
src 目录
简单粗暴把src移植过来,
复制src/pages,src/App.vue, src/index.html
复制src/main.js
报错:
控制台报错
main.js:121 Uncaught SyntaxError: Unexpected token !
at Object../src/main.js (app.js:2481)
at __webpack_require__ (app.js:770)
at fn (app.js:130)
at Object.1 (app.js:2555)
at __webpack_require__ (app.js:770)
at app.js:908
at app.js:911
命令行报错
* cube-ui in ./src/main.js
* cube-ui/lib/picker/index.js in ./src/main.js
* cube-ui/lib/picker/picker.min.css in ./src/main.js
* cube-ui/lib/picker/picker.min.js in ./src/main.js
* cube-ui/lib/picker/style.css in ./src/main.js
* mint-ui in ./src/main.js
* mint-ui/lib/style.css in ./src/main.js
* vconsole in ./src/main.js
* vue-lazyload in ./src/main.js
* vue-resource in ./src/main.js
原因:没有引入第三方库和文件
解决:
- 引入对应的less文件和js文件
- 安装第三方库
npm i --save vue-resource vue-lazyload mint-ui vconsole
- cube ui 引入 cube ui 在vue cli3中的引入方式和vue cli有所不同,具体步骤查看文档
vue add cube-ui
我这里是全局引入,因为原来的代码里也是全局引用的,其实应该按需引入的,这个等迁移工作完成后再优化,升级工作期间就不对业务代码做太大改动了
全局引入后,src目录会多一个cube-ui.js
文件
- 此时重启服务后,报错
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
(found in <Root>)
原因:引入的vue.js版本和main.js里的写法不匹配
解决:修改main.js
// 原来
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
// 修改
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
- 成功编译
复制路由文件
vue cli
的路由文件是放在 router
文件夹的, vue cli3 的路由在src/router.js
, 我沿用vue cli
的文件结构,依旧放在 router
文件夹里
引入路由文件后,报错:缺失components文件,接下来就
复制components文件夹
控制台疯狂报错,仔细看了下,有以下几种
- 文件名引入大小写问题
- 自定义指令文件, mixins文件还未引入
- 组件内引用的一些第三方库还没安装
npm i @chenfengyuan/vue-qrcode axios clipboard html2canvas particles.js swiper vue-awesome-swiper weixin-js-sdk --save
- less变量引用报错
解决:在vue.config.js引入全局less变量,参考vue cli3文档
const path = require('path')
module.exports = {
chainWebpack: config => {
const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
types.forEach(type =>
addStyleResource(config.module.rule('less').oneOf(type))
)
config.plugins.delete('prefetch')
},
css: {
loaderOptions: {
stylus: {
'resolve url': true,
import: []
}
}
},
pluginOptions: {
'cube-ui': {
postCompile: true,
theme: false
}
}
}
function addStyleResource (rule) {
rule
.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [
path.resolve(__dirname, 'src/assets/css/variable.less') // 需要全局导入的less
]
})
}
jQuery引用
项目还用了jquery
😭,用的地方还不少
解决:
npm install jquery --save
- 检查下
package.json
看是否已经引入了 .eslintrc.js
文件中,env
中 添加jquery:true
- vue.config.js 添加插件
const webpack = require('webpack')
module.exports = {
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'windows.jQuery': 'jquery'
})
]
},
}
- main.js:
import $ from 'jquery'
store文件引入
我的store文件是放在 store
文件夹的,迁移过去之后再更改main.js的引入路径即可
到这一步,项目基本就可以正常编译了,可以看到页面的基本轮廓,但还存在ui样式尺寸不对,请求跨域了等问题,依次解决
跨域
在vue.config.js中配置
devServer: {
port: 8080,
proxy: {
'/apis': {
target: 'http://dev.xxx.com',
changeOrigin: true,
pathRewrite: {
'/apis': ''
}
}
}
}
rem
修改 postcss.config.js
module.exports = {
plugins: {
autoprefixer: {},
'postcss-px2rem': {
remUnit: 75
}
}
}
好咯,到这一步,样式正常啦,请求也可以正常发送接收啦。
表面上看起来和正常的项目没什么区别了,可是一打开控制台,又看到一个报错..
vue-awesome-swiper
Swiper.vue?56a2:97 Uncaught (in promise) TypeError: _this.swiper.lockSwipes is not a function
at eval (Swiper.vue?56a2:97)
是swiper插件的报错,上网找了下原因:swiper 新版本没有了lockSwipes
这个api,替换成了 allowSlideNext
解决:
this.swiper.lockSwipes()
// 替换成
this.swiper.allowSlideNext = false
某些地方的icon有点错位
排查了下原因是全局引入的 cube-ui 的默认样式引起的,在reset.less文件加了句
body {
line-height: initial;
}
成功编译
至此为止,项目已经可以成功在 vue cli3 下跑起来啦。到处点一点,嗯,没什么报错了,接下来就来看看打包部分
打包
打包配置
原先的打包配置是在config/index.js
中
const path = require('path')
module.exports = {
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
// 输出静态资源路径
assetsRoot: path.resolve(__dirname, '../../../../resource'),
// 输出静态资源子目录
assetsSubDirectory: 'static',
assetsPublicPath: 'resource/',
}
}
项目打包后生成的 index.html 和生成的静态资源的目录是不同的,而且打包好的html文件引用的静态资源路径得是相对路径(因为想开发测试生产都用一套代码)
在vue.config.js中的配置也需要修改:
{
publicPath: process.env.NODE_ENV === 'production' ? './resource' : '/',
indexPath: path.resolve(__dirname, 'dist/index.php'),//输出html目录
outputDir: path.resolve(__dirname, '../../../resource'),// 静态资源目录
assetsDir: 'static',// 静态资源子目录
}
vue cli3的文档只是很简单的提到publicPath,assetsDir.. 谷歌了半天,查了好久的资料,终于让我找到了答案😭
CSS minification error
配置完成, npm run build
报错:
CSS minification error: Cannot read property 'type' of undefined. File: css/doubleEleven.08c6b745.css
这个坑爹的报错,让我整整花了半天时间,这个报错的资料超少,最后是在vue cli3 的一个issue上看到了, 这个issue还因为提问不规范被关闭了,不过让我看到了条评论是说可能是transform:rotate()
引起的。
虽然不知道为什么,我还是试了试查找了下项目代码,发现:
transform: rotate3d(0, 1, 00deg);
立马纠正,再次打包,打包成功,并且在开发,测试环境运行良好,耶️✌️
总结
😂升级的vue cli3后代码校验果真严格的好多,上面的错误在原来的编辑打包一点问题都没有,到这里就原形毕露了,不过总算完成了升级,在调试时明显感觉热更新速度提升了好多。
到此为止,这次的迁移工作就完成咯,当然还有些代码还得lint下或者手动修复下格式,这个就后续再做啦。