.ts-loader是如何與vue單文件組件銜接做用的vue
https://github.com/microsoft/TypeScript-Vue-Starternode
https://www.npmjs.com/package/ts-loaderwebpack
從文檔上能夠看到,須要安裝 typescript 和 ts-loader這兩個依賴git
ts-loader是如何處理.vue單文件組件的,github
在rule的配置裏,ts-loader的test是以.ts文件結尾的啊,下面研究下web
———————————————————————————————typescript
首先再來回憶一下vue-loader+VueLoaderPlugin的處理過程:npm
vueloaderplugin在webpack初始化的階段,api
vueloaderplugin擴展了開發者module.rule的配置,加入了vue-loader內部提供的pitcher-loader(即:pitcher這個rule,它的use是pitcher-loader), ui
(pitcher的resourceQuery是 request帶」vue」這個query的 (如xxx.xx?vue&xxx) )
並以這樣的順序將rule從新組合
[pitcher,…clone Rules,…vue-loader] (將vue-loader放到最後,將pitch-loader放到最開始)
pitcher-loader的匹配條件是,request中帶」vue」這個query (如xxx.xx?vue&xxx)
Step1:
當處理一個.vue文件的時候,vue-loader會判斷,若是request不帶type=vue,會生成下面這一大段js module:
"import { render, staticRenderFns } from "./index.vue?vue&type=template&id=2964abc9&"
import script from "./index.vue?vue&type=script&lang=ts&"
export * from "./index.vue?vue&type=script&lang=ts&"
/* normalize component */
import normalizer from "!../node_modules/vue-loader/lib/runtime/componentNormalizer.js"
var component = normalizer(
script,
render,
staticRenderFns,
false,
null,
null,
null
)
/* hot reload */
if (module.hot) {
var api = require("/Users/huhao/Desktop/demo/node_modules/vue-hot-reload-api/dist/index.js")
api.install(require('vue'))
if (api.compatible) {
module.hot.accept()
if (!api.isRecorded('2964abc9')) {
api.createRecord('2964abc9', component.options)
} else {
…
Step2:
而後開始對這個新生成的一坨jsmodule進行處理,依賴收集的過程當中,會拿到
import { render, staticRenderFns } from "./index.vue?vue&type=template&id=2964abc9&"
import script from "./index.vue?vue&type=script&lang=ts&"
export * from "./index.vue?vue&type=script&lang=ts&"
…
這些行request,而後對每一個request進行resolve,建立獨立的module..
由於request帶vue這個query,因此會先被pitcher-loader處理,pitcher在runLoaders過程當中操做,會第一個執行,剔除掉eslint-loader,剔除pitcher自身,根據不一樣的type=xxx 返回一段新的request,
..有template的..
..有style的..
..有script的..
而後咱們會發現這個時候處理script的生成的request,附帶了ts-loader了。
問題: 爲何script的部分生成的request。。直接就斷定附帶有ts-loader了
"/Users/huhao/Desktop/demo/node_modules/ts-loader/index.js??ref--2!/Users/huhao/Desktop/demo/node_modules/vue-loader/lib/index.js??vue-loader-options!/Users/huhao/Desktop/demo/src/index.vue?vue&type=script&lang=ts&"
咱們向前看,
在最後生成上面這坨request的過程前,會先通過build的過程,
在調用棧doBuild的時候,要執行runLoaders方法的時候,this.loaders就已經包括ts-loader了
🤔
在build以前是建立module和resolve的過程,看一下建立module的過程,
在normalModule.factory中 會使用rulest.exec({})對resouce("./index.vue?vue&type=script&lang=ts&")進行操做,根據webpack的rule規則,去和webpack的options中配置的loader進行過濾,解析出本次構建module過程當中可使用的loader,
注意,此時是在對step2中收集依賴時收集的 import script from "./index.vue?vue&type=script&lang=ts&" 進行操做。
下面要進行exec了, 能夠看到 rules是webpack處理獲得的全部rules 要從裏面篩選出本次構建module可用的loaders
exec裏面會執行run方法, run方法會接觸到這一大坨過濾條件, 若是都知足了,纔會將這個loader加入到result中
這個方法裏有一個rule.resourceQuery, 這時候會發現對/.tsx?$/結尾的這種rule的resourceQuery其實已經被vueLoaderPlugin改寫過了 ,
在vue-loader的 plugin.js的 cloneRule方法中:
對webpack的除了,/.vue$/的rule,的resource過濾和resourceQuery過濾重寫了…
看一下重寫的resourceQuery裏:
加了這句話,
const fakeResourcePath = `${currentResource}.${parsed.lang}`
主要是這句話,fakeResourcePath…
fakeResourcePath的值是
因此在exec的過程當中,拿webpack的rules過濾loaders的過程當中,ts-loader會加入構建,由於..
全部resourcePath被加入了parsed.lang了
由於ts-loader的條件是
以’ts’或’tsx’結尾的能經過他的條件篩選
資料:
1. ruleSet的使用機制: https://github.com/CommanderXL/Biu-blog/issues/30