Vue3.0 踩坑

Posted by Youzi on February 23, 2021

项目升级 Vue3.0

配置相关

在·Vue-cli 3.0·以后的版本,其实该脚手架针对·webpack·已经内置好了很多默认配置,对于 webpack 的默认配置,像常用的·plugin·,有两种方式对其默认值进行修改;

官网介绍配置 webpack 相关的内容:https://cli.vuejs.org/zh/guide/webpack.html

  1. configureWebpack:这种方式可以接受对象或返回值为对象的函数,直接使用这种方式,会全量覆盖掉默认配置,比如有的配置只是想修改某个属性,但是会连同其他属性都被覆盖掉,因为在·configureWebpack·下配置,例如·plugin·,都需要调用plugins: [new MyAwesomeWebpackPlugin()],可以看到会·new·一个新的对象,所以默认配置会被覆盖掉,如果想完全重新配置内置·webpack·,这种方式是可取的;
  2. chainWebpack:这种方式多数是链式操作的集合,该属性的值是接受·config·对象为参数的函数,并返回新的配置;这种方式的好处就是不会全部覆盖默认配置,而且类似merge的方式,合并现有的和默认的配置;

遇到的问题及解决方案

IE 打包后的兼容性问题

首先把文档摆出来:浏览器兼容性#browserslist;要解决兼容性问题,通常借助babel-polyfill将 JS 编译为 ES5 或者更低级的版本;

文档里比较详细的写明了如何利用browserslist@vue/cli-plugin-babel插件来做polyfill,很多时候不用特意去配置,就可以使项目在 IE 等浏览器下运行起来,因为默认配置vue-cli已经为我们做好了;

同时,在文档里也提到了,默认情况下不会对第三方库也就是node_modules里的内容进行polyfill,在antdv的文档里就提到了,需要手动去对这个库做polyfill,需要我们自己在vue.config.js去配置,配置如下:

1
2
3
module.exports = {
  transpileDependencies: ['ant-design-vue']
};

当然也有一种全量引入所有polyfill函数的方法,在.babelrc(babel 的配置文件)中,添加:

1
2
3
4
5
6
7
8
9
10
{
  "presets": [
    [
      "@vue/app",
      {
        "useBuiltIns": "entry"
      }
    ]
  ]
}

在入口文件main.js中添加:

1
2
3
4
5
import '@babel/polyfill';

// 或者
import 'core-js/stable';
import 'regenerator-runtime/runtime';

这样就全量引入了所有的polyfill函数,也不用担心三方库的兼容性了。

生产环境将第三方库作为 CDN 引入

解决方案 1

开发时经常要区分生产的·index·入口和开发的·index-dev·,配置如下:

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
module.exports = {
  // 第一种方式,会覆盖掉默认配置
  configureWebpack: () => {
    if (process.env.NODE_ENV === 'production') {
    }
    // 开发环境配置的插件
    else {
      plugins.push(
        new HtmlWebpackPlugin({
          filename: 'index.html',
          template: './public/index-dev.html',
          title: 'test',
          inject: true
        })
      );
    }
  },
  // 第二种方式,不会覆盖默认配置
  chainWebpack: config => {
    config.plugin('html').tap(args => {
      Object.assign(args[0], {
        template: './public/index-dev.html',
        title: 'test'
      });
      console.log(args);
      return args;
    });
  }
};

使用第一种方式,会导致我们在.env文件下配置的环境变量NODE_ENV,BASE_URL,VUE_APP_等内容就会失效了,所以应该采用第二种方式;

解决方案 2

也可以直接使用·externals·的新特性,在 GitHub 找到了相关·issue·,https://github.com/vuejs/vue-cli/issues/6149

总结下来就是:

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = {
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      return {
        externalsType: 'script',
        externals: {
          vue: ['https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js', 'Vue']
        }
      };
    }
  }
};

全局引入样式变量

sass/scss

sass 引入样式变量比较简单,文档中https://cli.vuejs.org/zh/guide/css.html#%E5%90%91%E9%A2%84%E5%A4%84%E7%90%86%E5%99%A8-loader-%E4%BC%A0%E9%80%92%E9%80%89%E9%A1%B9,配置相关的 css-loader 就行了;

less

less 配置有两种方式,一种是上面的在 css-loader 里面,添加globalVars属性,这样less-loader就会注入这些变量到代码中,编译的时候就可以被替换掉;

还有一种方案,利用vue-cli-plugin-style-resources-loader || style-resources-loader两个 loader 插件,在vue.config.js里添加如下配置:

1
2
3
4
5
6
7
8
module.exports = {
  pluginOptions: {
    'style-resources-loader': {
      preProcessor: 'less',
      patterns: [path.resolve(__dirname, './src/style/index.less')]
    }
  }
};

深度选择器

在 2.0 时,使用的深度选择器是 vue-loader 文档里的>>> | ::v-deep | /deep/这几个选择器,文档:https://vue-loader.vuejs.org/zh/guide/scoped-css.html#%E6%B7%B1%E5%BA%A6%E4%BD%9C%E7%94%A8%E9%80%89%E6%8B%A9%E5%99%A8,目前在项目中用到的时候,dev 编译时会出现[@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead.,又出现了新的写法:

// 在less里
:deep(.van-search) {
  // ...
}

transition 组件的修改

2.0 版本,总共有 6 个 class 变化,依次是:

  1. v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  3. v-enter-to:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
  4. v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  6. v-leave-to:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 `v-leave 被删除),在过渡/动画完成之后移除。

3.0 版本 class 名改为:

  1. v-enter-from:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  3. v-enter-to:定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter-from 被移除),在过渡/动画完成之后移除。
  4. v-leave-from:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  6. v-leave-to:离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave-from 被删除),在过渡/动画完成之后移除。