標籤:

webpack中 vue + ts + jsx應該怎麼配置?

現在配置了vue + typescript但是如何在class風格組件中使用jsx呢?


折騰不一定能提高生產力,但是不折騰一定不能提高生產力。—— 魯迅

瀉藥。

TS的星星之火現在已經可以燎原了,TS + React、TS + Angular已經普及在很多新項目中。Vue似乎稍稍落後了一小步,不過目前的生態也還不錯了。

不知道題主目前處於什麼狀態,因此就從頭寫起好了~

Class風格

在ES6、ES7中,我們可以使用Class、Decrator等新特性讓我們的代碼更便於書寫。在TS中,這些寫法的優勢尤為明顯,因此在接入TS之前,我們需要先掌握下面幾個最佳實踐:

  • vue-class-component
  • vuex-class
  • vue-property-decorator

伸手黨福利

如果你想快速開始一個新的TS項目,可以使用餓了么提供的TS模板。

vue init ElemeFE/webpack-typescript ts-vue

DIY

初始化

如果你想一步步實現自己的個性化配置,可以從這裡看。

這裡我使用的是webpack模板建立項目:

vue init webpack ts-vue
// 我的依賴
Project name ts-vue
Project description A Vue.js project
Author geovanni.zhang
Vue build standalone
Install vue-router? Yes
Use ESLint to lint your code? Yes
Set up unit tests Yes
Pick a test runner jest
Setup e2e tests with Nightwatch? Yes

安裝依賴

npm install
npm install typescript ts-loader --save-dev

配置TS解析

在build/webpack.base.con.js中添加規則,使webpack能夠解析.vue文件。同時在resolve中添加ts後綴,使webpack中能夠解析.ts文件:

module.exports = {
...
resolve: {
extensions: [".js", ".ts", ".vue", ".json"],
alias: {
"vue$": "vue/dist/vue.esm.js",
"@": resolve("src"),
}
},
module: {
rules: [
{
// 對所有引入的tsx文件進行解析
test: /.tsx?$/,
loader: "ts-loader",
exclude: /node_modules/,
options: {
// 自動將所有.vue文件轉化為.vue.tsx文件
appendTsSuffixTo: [/.vue$/]
}
}
]
}
...
}

為每個文件聲明全局模塊.vue,這樣每個單文件組件就可以被自動被聲明了。

在src目錄下建立一個文件vue.d.ts:

declare module "*.vue" {
import Vue from "vue";
export default Vue;
}

在根目錄下建立配置文件tsconfig.json

{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"sourceMap": true,
"strict": true,
"module": "es2015",
"moduleResolution": "node",
"target": "es5"
}
}

重命名所有JS文件為TS文件。

如果這是一個新的項目應該只有src/main.js和src/router/index.js。

-- src
-- main.js
-- router
-- index.js

回到build/webpack.base.conf.js文件中,修改入口文件的後綴:

module.exports = {
entry: {
app: "./src/main.ts"
}
}

在所有文件中,引入.vue文件時,.vue不能省略。

這是因為我們實際引用的是App.vue.tsx,tsx已經被省略了。在這裡修改src/main.js:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from "vue"
import App from "./App.vue"
import router from "./router"

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
el: "#app",
router,
template: "&",
components: { App }
})

修改src下的所有vue文件,將script的語言設置為ts,並添加聲明:

// HelloWorld.vue
&

npm install --save-dev vue-class-component

修改tsconfig.json,添加裝飾器模式:

{
"compilerOptions": {
"jsx": "preserve",
"jsxFactory": "h",
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true, // 主要是這一行
"sourceMap": true,
"module": "es2015",
"moduleResolution": "node",
"target": "es5"
}
}

現在我們可以使用class風格進行編寫了,修改HelloWorld組件:

&

npm install
babel-plugin-syntax-jsx
babel-plugin-transform-vue-jsx
babel-helper-vue-jsx-merge-props
babel-preset-es2015
--save-dev

接的在.babelrc文件中註冊插件:

{
...
"plugins": ["transform-runtime", "transform-vue-jsx"],
...
}

我們來修改一下原來的組件,將template換為JSX:

// 這裡我們設置為tsx
&

首先安裝需要的依賴包:

npm install --save-dev tslint tslint-loader tslint-config-standard

修改build/webpack.base.conf.js中的匹配規則,對於ts和tsx文件在編譯前先進行校驗:

module: {
rules: [
...
{
test: /.tsx?$/,
exclude: /node_modules/,
enforce: "pre",
loader: "tslint-loader"
}
...
]
...
}

在build/vue-loader.conf.js中,添加開啟TSLint進行預處理:

module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ["src", "poster"],
source: "src",
img: "src",
image: "xlink:href"
},
ts: ["ts-loader", "tslint-loader"]
}

在根目錄下添加TSLint的配置文件,這裡我是這樣配置的:

{
"extends": "tslint-config-standard",
"globals": {
"require": true
},
"rules": {
"no-consecutive-blank-lines": false
}
}

重新運行,就可以看到warning啦~

結束

閑逛的時候發現有個同學已經寫了demo,這裡放個鏈接,向先人star~

以上~


我有一個repo,同時有lang="ts"和lang="tsx"兩種vue,以及純tsx和ts文件,正在整理總結,晚點放出

repo地址: https://github.com/Plasmatium/amazing-canvas-collection


網上有一些其他的教程,提到了各種需要安裝的包和一些操作,實現了部分typescript、jsx、單文件vue的組合,比如單獨的tsx(通過import導入template和css),單文件vue啟用&