ts-loader如何與vue單文件組件銜接


.ts-loader是如何與vue單文件組件銜接作用的

 

首先看一下官方的starter pack

 

 

 

 

https://github.com/microsoft/TypeScript-Vue-Starter

https://www.npmjs.com/package/ts-loader

 

從文檔上可以看到,處理單文件組件安裝了 typescript 和 ts-loader這兩個依賴。

 

 

 

ts-loader是如何處理.vue單文件組件的,

rule的配置里,ts-loader的test是以.ts文件結尾的啊,下面研究下 

 

———————————————————————————————

 

 

首先再來回憶一下vue-loader+VueLoaderPlugin的處理過程:

 

 

 

vueloaderplugin在webpack初始化的階段,

 

vueloaderplugin擴展了開發者module.rule的配置,加入了vue-loader內部提供的pitcher-loader(即:pitcher這個rule,它的use是pitcher-loader),  

       (pitcher的resourceQuery是 request帶”vue”query的 (如xxx.xx?vue&xxx) )

 

 

並以下面這個順序將rules重新組合

 

[pitcher,…clone Rules,…vue-loader] (將vue-loader放到最后,將pitch-loader放到最開始,中間是被重寫過fakeResourcepath的clone Rules)

 

(pitcher-loader的匹配條件是,request中帶”vue”這個query  (如xxx.xx?vue&xxx))

 

 

 

 

Step1:

當處理一個.vue文件的時候,vue-loader會判斷,如果request不帶type=vue,會生成下面這一大段js module:

 

這就是第一步, 這里一個.vue文件會被處理成下面的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&"

 

 

/* 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:

webpack中的acron開始對這個新生成的一坨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的..

 

然后我們debug會發現,這個時候處理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&"

 

 

問題: 為什么script block的部分生成的request。。直接就判定附帶有ts-loader了

 

 

 

 

繼續向前看,

 

 

 

在最后生成上面這坨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,看看為什么這里會把ts-loader也加入了進來

 

 

 

 

 

注意,此時是在對step2中收集依賴時收集的 import script from "./index.vue?vue&type=script&lang=ts&" 進行操作。

 

 

繼續向前debug,下面要進行exec了, 可以看到 rules是webpack處理得到的所有rules 要從里面篩選出本次構建module可用的loaders

 

 

 

 

exec里面會執行run方法, run方法會接觸到這一大坨過濾條件, 如果都滿足了,才會將這個loader加入到result中

 

 

 

這個方法里有一個rule.resourceQuery, 這時候會發現對/.tsx?$/結尾的這種rule的resourceQuery已經被vueLoaderPlugin改寫過了

 

 

 

 

 

     在vue-loader的 plugin.js的 cloneRule方法中:

 

      會對webpack的所有配置的rules中除了,/.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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM