TypeError: loaderContext.getOptions is not a function

hdxg發表於2024-04-22

最近建立新的vue3+ts+electron專案,結果npm run electron:serve時報以上錯誤。

報錯點

報錯資訊:

Module build failed (from ./node_modules/ts-loader/index.js):
    at getLoaderOptions (D:\projects\my-project\node_modules\ts-loader\dist\index.js:112:41)
    at Object.loader (D:\projects\my-project\node_modules\ts-loader\dist\index.js:15:21)

報錯的點來自檔案node_modules\ts-loader\dist\index.js。

也就是ts-loader想使用getOptions()這個方法,但是沒有。

loaderContext.getOptions()

從參考資料1可知,loaderContext.getOptions()是webpack中的一個API,但是後來被移除了。

會不會我現在使用的webpack版本太高了,getOptions()沒了?於是我執行npm list webpack檢視一下webpack的版本:

npm ERR! code ELSPROBLEMS
npm ERR! invalid: webpack@5.91.0 D:\projects\my-project\node_modules\webpack
dev-assistant@0.1.0 D:\projects\my-project
├─┬ @vue/cli-plugin-babel@5.0.8
│ ├─┬ babel-loader@8.3.0
│ │ └── webpack@5.91.0 deduped
...

一看是webpack@5。

於是我搜尋"webpack@5 getOptions",找到參考資料2,從中得知似乎webpack5中移除了getOptions()。

但是我隨後查了一下webpack的官網(參考資料4),得知webpack@5中是有getOptions()的,它將getOptions()內建了,用來代替loader-utils中的getOptions()方法。

為了再次驗證一下,我開啟ts-loader@9的package.json檢視一下webpack的版本:

  "devDependencies": {
  	...
    "typescript": "^5.2.2",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0"
  },

確實也是webpack@5。

難題

既然webpack@5中有getOptions(),那為什麼ts-loader@9執行的時候會訪問不到getOptions()?

思路到這裡就斷了...

對比之前的專案

我前兩天也建立過同樣的vue3+ts+electron專案,為什麼那時候可以執行呢?

開啟之前專案的package.json:

  "devDependencies": {
    "@types/electron-devtools-installer": "^2.2.0",
    "@typescript-eslint/eslint-plugin": "^4.18.0",
    "@typescript-eslint/parser": "^4.18.0",
    "@vue/cli-plugin-babel": "~4.5.19",
    "@vue/cli-plugin-eslint": "~4.5.19",
    "@vue/cli-plugin-router": "~4.5.19",
    "@vue/cli-plugin-typescript": "~4.5.19",
    "@vue/cli-plugin-vuex": "~4.5.19",
    "@vue/cli-service": "~4.5.19",
    "@vue/compiler-sfc": "^3.0.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^7.0.0",
    "electron": "^13.0.0",
    "electron-devtools-installer": "^3.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-vue": "^7.0.0",
    "prettier": "^2.2.1",
    "sass": "^1.26.5",
    "sass-loader": "^8.0.2",
    "typescript": "~4.1.5",
    "vue-cli-plugin-electron-builder": "~2.1.1"
  },

發現這裡的cli-plugin-typescript的版本是~4.5.19,與之對應的cli-service也是~4.5.19。

而我現在建立的專案package.json:

  "devDependencies": {
    "@types/electron-devtools-installer": "^2.2.0",
    "@typescript-eslint/eslint-plugin": "^5.4.0",
    "@typescript-eslint/parser": "^5.4.0",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-plugin-router": "~5.0.0",
    "@vue/cli-plugin-typescript": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "@vue/eslint-config-typescript": "^9.1.0",
    "electron": "^13.0.0",
    "electron-devtools-installer": "^3.1.0",
    "eslint": "^7.32.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-vue": "^8.0.3",
    "prettier": "^2.4.1",
    "sass": "^1.32.7",
    "sass-loader": "^12.0.0",
    "typescript": "~4.5.5",
    "vue-cli-plugin-electron-builder": "~2.1.1"
  }

好像發現問題所在了...,升級了大版本。會不會就是這裡引入了bug。

嘗試降級

那麼現在的問題就是如何在使用vue create建立專案時,使用4.5.19這個版本呢。

經過一番查詢和命令列操作,得知vue create建立專案時依賴使用的版本號與@vue/cli的版本一致。

於是修改全域性的@vue/cli版本:

npm i @vue/cli@4 -g

然後再建立專案vue create xxx

Vue CLI v4.5.19
Failed to check for updates
✨  Creating project in D:\projects
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while...

ERROR  Failed to get response from https://registry.npm.taobao.org/binary-mirror-config
[..................] / idealTree:dev-assistant: sill idealTree buildDeps

看到兩行錯誤資訊:

Failed to check for updates
...
ERROR  Failed to get response from https://registry.npm.taobao.org/binary-mirror-config

啥?

幸好最近正好看到一篇文章說淘寶的npm映象廢棄的事情。於是開啟.vuerc:

{
  "useTaobaoRegistry": true,
}

將useTaobaoRegistry修改為false。

注意,淘寶原映象廢棄,但還有新的映象。如果不加操作,執行vue create仍然會卡死。正確的做法是使用nrm切換registry到taobao新映象源。

最後,成功執行!

參考資料

  1. loaderContext.getOptions is not a function
  2. webpack5中的getOptions沒了?
  3. TypeError: loaderContext.getOptions is not a function
  4. [this.getOptions()](

相關文章