Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue升级到2.7&增加对TypeScript的支持 #66

Open
z0nka1 opened this issue Mar 13, 2023 · 0 comments
Open

Vue升级到2.7&增加对TypeScript的支持 #66

z0nka1 opened this issue Mar 13, 2023 · 0 comments

Comments

@z0nka1
Copy link
Owner

z0nka1 commented Mar 13, 2023

一、升级前环境:

  • nodejs: 10.9.0
  • webpack: 3.6.0
  • vue: 2.6.10
  • vue-loader: 13.3.0
  • vue-style-loader: 3.0.1

二、升级vue

  • vue 2.6.10 -> 2.7.14
  • vue-loader 13.3.0 -> 15.10.0
  • vue-style-loader 3.0.1 -> 4.1.3
  • 删除 vue-template-compiler(vue2.7不再需要)

重新安装依赖后,需要在webpack配置的plugins中加入VueLoaderPlugin

// webpack.config.js
const { VueLoaderPlugin } = require('vue-loader');

plugins: [
  new VueLoaderPlugin()
]

改好后重启项目。

好的,第一个报错来了:

Cannot read property 'compilation' of undefined
VueLoaderPlugin.apply ...

从报错信息栈可以看到,错误最先是从VueLoaderPlugin报出来的。
首先想到的就是版本不兼容。因为想要模板内表达式支持ts,所以vue-loader选择了16.8.0版本。尝试降到vue2.7最低要求版本15.10.1(见迁移指南

降低vue-loader版本后,第二次重启项目,上述问题得到解决。

这时出现的另外一个报错是:

error  in ./node_modules/pdfjs-dist/build/pdf.js

Module parse failed: Unexpected character '#' (1413:9)
You may need an appropriate loader to handle this file type.
| 
| class PDFDocumentLoadingTask {
|   static #docId = 0;
| 
|   constructor() {

 @ ./src/views/excitation/contractManage/pdfjs-webpack.js 1:12-46
 ...

以及另外一个很相似的报错:

error  in ./node_modules/@kk/utils/src/axiosconf.js

Module parse failed: Unexpected token (37:16)
You may need an appropriate loader to handle this file type.
|     }
|     let user_agent_mini = decodeURIComponent(qs["useragent"] ? qs["useragent"] : "");
|     headers = { ...headers, ...{ "User-Agent-Mini": user_agent_mini } }
|     return headers;
| }

 @ ./node_modules/@kk/utils/src/index.js 14:0-19:21
 ...

上面两个报错信息都比较直白,这些文件用了js新语法,我们需要用合适的loader去转换他们:

{
        test: /\.js$/,
        loader: 'babel-loader',
        include: [
          resolve('node_modules/pdfjs-dist'),
          resolve('node_modules/@kk/utils')
        ]
      }

上面问题解决之后,接着出现的报错:

warning  in ./src/icons/svg/yellow_v.svg

svg-sprite-loader exception. 31 rules applies to /Users/admin/Desktop/kkworld/code/temp/kk-ecology/src/icons/svg/yellow_v.svg

 @ ./src/icons/svg nonrecursive \.svg$

报错信息不是很明确,只知道问题出在svg-sprite-loader,首先考虑版本不兼容问题,升级svg-sprite-loader3.5.2 -> 5.2.1。
看来猜测没错,这个问题也解决了。

至此项目可启动成功!

测试一下,可以用新语法了:

<script setup>
import { onMounted, ref } from 'vue';

const refV = ref(0);
refV.value++;

onMounted(() => {
  console.log('ref:', refV.value);
});
</script>

三、增加ts支持

1、安装typescript、ts-loader最新版本:

npm i -D typescript ts-loader

此时安装到的版本分别是:

  • typescript: ^4.9.5
  • ts-loader: ^9.4.2

依赖安装完毕,创建ts配置文件tsconfig.json

// tsconfig.json
{
  "compilerOptions": {
    "allowJs": true,
    "baseUrl": ".",
    "esModuleInterop": true,
    "module": "CommonJS",
    "moduleResolution": "node",
    "noImplicitAny": false,
    "outDir": "./built",
    "paths": {
      "@\/*": [
        "src/*"
      ]
    },
    "strict": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "target": "es5",
    "lib": ["DOM", "ES2015"],
    "jsx": "preserve"
  },
  "vueCompilerOptions": {
    "target": 2.7
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "types/**/*.d.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

创建全局声明文件global.d.ts,内容根据项目需要加入,比如:

declare namespace Sentry {
  function init(options): void;
  function withScope(func: Function): void;
  function captureException(err: any, level: any): void;
  function captureMessage(err: any, level: any): void;
}

下一步是入口文件main.js改为main.ts,同时修改webpack配置:

// webpack.config.js
entry: {
-  app: ['./src/main.js']
+  app: ['./src/main.ts']
},
resolve: {
-  extensions: ['.js', '.vue', '.json']
+  extensions: ['.js', '.ts', '.tsx', '.vue', '.json']
},
module: {
  rules: [
+    {
+      test: /\.tsx?$/,
+      loader: 'ts-loader'
+    }
  ]
}

这一切改好之后启动项目。

得到的第一个报错信息是:

error  in ./src/main.ts

Module build failed: TypeError: loaderContext.getOptions is not a function
    at getLoaderOptions (/Users/admin/Desktop/kkworld/code/temp/kk-ecology/node_modules/ts-loader/dist/index.js:91:41)
    at Object.loader (/Users/admin/Desktop/kkworld/code/temp/kk-ecology/node_modules/ts-loader/dist/index.js:14:21)

 @ multi (webpack)-dev-server/client?http://0.0.0.0:8082 webpack/hot/dev-server babel-polyfill ./src/main.ts

查了下ts-loader文档,因为我们用的是webpack3.6.0版本,所以不能用太新的ts-loader,不适配,降级到ts-loader@^3.5.0,问题解决。

接着第二个报错:

error  in ./src/main.ts

[tsl] ERROR in /Users/admin/Desktop/kkworld/code/temp/kk-ecology/src/main.ts(7,17)
      TS2307: Cannot find module './App' or its corresponding type declarations.

原因是ts文件识别不了.vue文件,需要增加声明文件d.ts:

declare module '*.vue' {
  import type { DefineComponent } from 'vue';
  const component: DefineComponent<{}, {}, any>;
  export default component;
}

到这里,项目可以正常启动了,测试一下.vue文件能不能正常使用ts:

// UseTs.vue
<script lang="ts">
const num: number = 0;
const func = (): void => {
  console.log('num', num);
}
func();
</script>

发现报错了:

Module build failed: Error: Could not find source file: 'path-to-file/UseTs.vue'.

原因可以参考ts-loader文档,解决方式:

{
  test: /\.tsx?$/,
  loader: 'ts-loader',
+  options: {
+    appendTsSuffixTo: [/\.vue$/]
+  }
}

至此ts就可以在项目中正常使用了。

四、总结

升级过程中遇到报错,首先应该考虑版本不兼容问题,查找解决方案也建议首先从官方文档、github issues方面着手。

以上是在对同一个项目进行两次升级后总结的改动较小又行之有效的方案。

在第一次升级中,我首先对项目的webpack版本进行了升级,从3.6.0升到4.46.0,并且顺利完成了vue升级和ts支持。
但是因为webpack3到webpack4的api改动较大,以及相关的plugin、loader等也有较大变动,导致升级后配置无法与当前配置完全等价替换,
因担心由此带来的影响,所以放弃了这个方案。

上文中提到的方案,不需要升级webpack,对项目影响较小。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant