Transpile Webpack Plugin:讓 Webpack 按照原始檔的目錄結構輸出

烏柏木發表於2022-12-28

作為 Web 開發者,你是否也糾結過如何用 Webpack 做檔案轉譯?就像 Babel CLI 轉譯檔案那樣按照原始檔的目錄結構輸出?如果有,那麼這篇文章就是為你而寫,我們一起瞧一瞧怎麼做吧。

Webpack 與 bundling

Screen Shot 2022-12-27 at 11.06.01.png

在平日的印象中,似乎 Webpack 就等於 bundling,就如官方文件首頁寫的那樣 "bundle your ...",看上去 Webpack 就是來做 bundling 的。在瀏覽器上,bundles 確實很不錯,能夠以非常合理的策略載入和執行。但在 NodeJS 中,事情就變得有點不同了。

在 NodeJS 中,以分檔案的方式組織和執行 JS 檔案通常是更自然的實踐,主要是因為原始檔路徑相關的邏輯有時是避免不了的,比如:在雲函式或 Serverless 中註冊事件、在某些 CLI 輔助下生成的原始碼。然而,想要在這基礎上新增服務端渲染(SSR)邏輯,考慮到前端部分可能已經用 Webpack 引用了各式各樣的檔案,後端部分可能也不得不用 Webpack 做 bundling。但這也意味著,我們不得不做相當量的工作來讓 bundles 可以合理適配這些原始檔路徑相關的邏輯。

為了更輕鬆的在 NodeJS 中使用 Webpack,Transpile Webpack Plugin(transpile-webpack-plugin) 便誕生了。這個外掛能夠將 entry 引用到的全部檔案列為輸入檔案,經過編譯,再按照相同的目錄格式輸出到輸出目錄中。我們一起看一下用法吧。

基本用法

給定在目錄 src 下有 2 個檔案,其中一個匯出字串常量,另一個引用這個常量然後列印出來。初始的檔案結構大體如下:

.
├── src/
│   ├── constants.js
│   └── index.js
├── package.json
└── webpack.config.js

現在,我們要把目錄 src 下的檔案使用 Webpack 轉譯到目錄 dist 下,像這樣:

.
├── dist/
│   ├── constants.js
│   └── index.js
...

首先,我們需要保證 webpack(v5) 和 webpack-cli(v4) 已經安裝好:

$ npm i -D webpack webpack-cli

然後,安裝 transpile-webpack-plugin(v1):

$ npm i -D transpile-webpack-plugin

之後,調整 webpack.config.js

const TranspilePlugin = require('transpile-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: __dirname + '/dist',
  },
  plugins: [new TranspilePlugin()],
};

最後,執行 npx webpack。這樣,所有直接或間接被 entry 引用到的檔案都會被收集為輸入檔案,之後,以輸入檔案的共有路徑為基準目錄,計算得到輸出目錄下各個檔案的相對輸出路徑,再以這些路徑生成輸出檔案,保留原始檔的目錄結構。我們可以透過 node dist/index.js 或檢視生成的程式碼來驗證輸出。

處理 SSR

假設有前端部分已用 Webpack 搭建完畢,其中涉及了各種檔案的轉換和非 JS 靜態資源的 emitting,現在想要在後端部分(NodeJS 伺服器)做 SSR,但在執行時保留原始檔的目錄結構。

那麼我們只需要複用前端部分的 Webpack 配置的基礎上,關閉所有非 JS 靜態資源的 emitting、將 new TranspilePlugin() 加入到 plugins 即可。Transpile 外掛已經經過了嚴格測試可以完好相容包括 resolve 別名、externals、source map 等在內的各種 Webpack 設定。

更多用法

Transpile 外掛有著若干個可用的配置項,其中最有常用的兩個可能是 longestCommonDirextentionMapping

預設情況下,Transpile 外掛使用輸入檔案的共有目錄作為基準目錄計算各個輸出檔案在輸出目錄下的相對路徑。但有時輸入檔案可能會在巢狀比較深的目錄下面,如果我們想要保留這種巢狀結構,就可以使用 longestCommonDir。給定輸入檔案 src/server/index.jssrc/server/constants/greeting.js 和輸出目錄 dist,當這個配置為 undefined,輸出檔案會是 dist/index.jsdist/constants/greeting.js。而這個配置為 './src',輸出檔案會是 dist/server/index.jsdist/server/constants/greeting.js

預設情況下,Transpile 外掛生成的輸出檔案具有與輸入檔案相同的檔名。(NodeJS 會把不認識字尾的檔案視為 JS 檔案。)但有時我們會想變換一下檔案字尾,比如從 .ts 變換為 .js,那麼透過配置項 extentionMapping 為 { '.ts': '.js' } 就可以做到。

討論問題?

希望 Transpile Webpack Plugin(transpile-webpack-plugin) 讓我們更輕鬆的在 NodeJS 中使用 Webpack。有任何問題或任何建議,可以在評論區留言或直接在 transpile-webpack-plugin/issues 發起 issue,歡迎共同探討。

相關文章