如果在配置不當的 JavaScript 或 TypeScript 模組中遇到 import
關鍵字,就會出現 “無法在模組外使用 import 語句” 的錯誤訊息。
在 JavaScript 伺服器端執行時環境中,當 Node.js 期望使用 CommonJS 模組系統使用的 require
關鍵字時,使用 ECMAScript (ES) 編寫的模組的 import
語法通常會導致該錯誤。
TypeScript 支援不同的模組格式,但混淆 ES 和 CommonJS 模組匯入方法的編碼錯誤也會導致此錯誤。
在瀏覽器方面,當您沒有為 JavaScript 程式碼檔案使用捆綁程式時,通常會出現此錯誤。
本文探討了這三種錯誤來源,並詳細介紹了針對每種環境的解決方案。
如何在伺服器端 JavaScript 環境中解決錯誤
本節演示如何在伺服器端 JavaScript 環境中解決錯誤。
背景介紹
Node.js 預設使用 CommonJS 系統的 require
關鍵字。因此,除非將 Node.js 配置為支援 ES 模組語法,否則您將收到熟悉的錯誤。同樣,Node.js 需要 .mjs 副檔名才能識別和使用 ES 模組。
解決方案
除了使用 .mjs 之外,您還可以通過使用捆綁程式或使用 --experimental-modules
標誌執行 Node.js 來使舊版本的 Node.js 與當前的 ES 模組相容。否則,您可以將 package.json 檔案中的 type
欄位設定為 module
,如下所示:
{ "name": "test-package", "version": "1.0.0", "type": "module", "main": "app.js", "dependencies": { } }
(注意:您應在所有軟體包的 package.json 檔案中包含 type
屬性。這種做法便於識別所使用的模組系統,並確保庫之間的一致性)。
另一種避免錯誤的方法是確保 import
和 export
語法正確並能正確載入。關鍵是要始終使用相對檔案路徑、命名匯出、匯出副檔名,並避免預設匯出。
下面是一個例子:
//module import import { sampleFunction } from './sampleModule.js'; // function export export function sampleFunction() { // code goes here }
最後,應確保所有第三方庫與 ES 模組相容。有關資訊,請參閱 package.json 檔案中的庫文件。或者,使用捆綁程式轉譯程式碼,以便 JavaScript 環境可以理解。
如何在 TypeScript 環境中解決錯誤
本節演示如何在 TypeScript 環境中解決錯誤資訊。
模組背景
通過模組,您可以在一個專案中的多個檔案之間重用、組織和共享程式碼。ES 支援使用 import
和 export
關鍵字在不同檔案間共享程式碼的外部模組。
當使用 ES 模組語法而未配置 TypeScript 以使用它時,通常會在 TypeScript 環境中出現此錯誤。由於 TypeScript 是 JavaScript 的超集,它預設使用 CommonJS 語法進行匯入,即使用 require
而不是 import
。在這種情況下, import
語句會導致錯誤。儘管如此,正確配置 TypeScript 對它支援 ES 模組還是很有必要的。
如果使用了不正確的副檔名,也可能會遇到此錯誤。例如,在使用 ES 模組語法的 Node.js 環境中使用 TypeScript 時,要匯入的模組必須使用 .mjs 副檔名,而不是普通的 .js。
另一個常見的錯誤原因是,在使用 Webpack 等捆綁程式時,tsconfig.json 或 package.json 檔案中的 module
欄位配置不當。不過,您可以通過將 tsconfig.json 檔案中的模組和目標欄位設定為 ECMAScript
,在 TypeScript 中使用捆綁程式捆綁 ES 模組。這樣,Webpack 就能理解目標環境,並在轉譯程式碼時使用正確的副檔名。
解決方案
要使用 RequireJS 等模組載入器或 Webpack 等捆綁程式載入 ES 模組,請在 tsconfig.json 檔案中新增以下內容:
{ "compilerOptions": { "module": "es20215", "target": "es20215", "sourceMap": true } }
在上面程式碼的 compilerOptions
部分,module
和 target
欄位被設定為使用 es20215
模組。有了這些補充,你就可以在 TypeScript 環境中使用 import
和 export
語句,而不會導致錯誤。
由於 TypeScript 預設使用 CommonJS,如果沒有相應修改 tsconfig.json 檔案,就會導致錯誤資訊。
幸運的是,一旦你將 module
和 target
欄位設定為使用 ECMAScript
模組,你就可以使用 export
語句從一個模組匯出函式或變數,並使用 import
語句將另一個模組載入到當前模組的作用域中。這一過程在下面的程式碼中出現:
// sum.ts export function sum(a: number, b: number, c: number): number { return a + b + c; } // main.ts import { sum } from './sum'; console.log(add(4, 4, 9));
如果您使用的是舊版本的 Node.js,可以使用 --experimental-modules
標誌執行程式碼,從而啟用 ES 模組支援。您還應該使用 Webpack、Browserify 或 Rollup 等捆綁程式捆綁所有 ES 程式碼,並將其輸出到一個檔案中。確保它是瀏覽器和舊版 Node.js 可以理解的版本,並在專案根目錄下設定一個 Webpack.config.js 檔案,指定模組型別。
下面是從 Webpack 文件中摘錄的一個示例:
module.exports = { entry: './src/index.ts', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, resolve: { extensions: ['.ts', '.js', '.mjs'] }, module: { rules: [ { test: /.ts$/, use: 'ts-loader', exclude: /node_modules/ } ] }, experiments: { outputModule: true } };
編譯後的程式碼會輸出到專案根目錄下 dist 目錄中的 bundle.js 檔案中。
您還可以使用 es-module-shims
等多填充程式,以不支援 ES 模組 import
和 export
語句的舊版瀏覽器為目標。
如何解決瀏覽器端 JavaScript 中的錯誤
本節將介紹如何在瀏覽器端 JavaScript 環境中解決錯誤。
瀏覽器背景
大多數現代瀏覽器(包括 Chrome、Firefox、Edge 和 Safari)都支援 ES 模組,因此不需要使用瀏覽器多填充程式、捆綁程式或轉譯程式。
如果您使用基於 React 或 Vue JavaScript 的前端庫,也不需要這些工具,因為它們預設支援 ES imports
和 exports
欄位。不過,舊版瀏覽器不支援 ES 語法,因此需要這些工具來實現跨平臺相容性。
在舊版瀏覽器中最常見的錯誤原因是頁面的 HTML 檔案不包含 type="module"
屬性。在這種情況下,出現錯誤的原因是網路上執行的 JavaScript 不支援 ES 模組語法。對於通過網路傳送的 JavaScript 程式碼,當嘗試從不同域載入 ES 模組時,可能會遇到跨源資源共享錯誤。
解決方案
為防止在舊版瀏覽器中出現模組錯誤,請確保在 HTML 根檔案中使用正確的 script
標記屬性 – type="module"
。或者,也可以使用 Webpack 對程式碼進行轉譯,以便舊版瀏覽器能夠理解。
要使用 type="module"
屬性,請在 HTML 根檔案中加入以下一行:
<script type="module" src="app.js"></script>
確保 import
檔案路徑有效和使用正確的 import
語法同樣重要。
此外,還可以訪問 Can I Use 等網站,確認 ES 模組的瀏覽器相容性。
最後,由於使用 .js 副檔名是常見做法,作為一種變通方法,您可以在模組的 HTML 檔案 script
標記中設定 type
屬性。將此屬性設定為 module
,瀏覽器就會忽略 .js 副檔名,將檔案視為模組。
小結
“Cannot use import statement outside a module”錯誤出現的原因有很多,具體取決於您是在瀏覽器端還是伺服器端 JavaScript 環境中。語法錯誤、配置不當和不支援的副檔名仍然是該錯誤最常見的幾種原因。
雖然大多數現代瀏覽器都支援 ES 模組,但您必須確保與舊版瀏覽器相容。通過 Webpack 等捆綁程式,您可以將所有原始碼及其依賴項編譯為舊版瀏覽器可以理解的單一輸出。
記得在 HTML 檔案中新增 type="module"
屬性,以告知瀏覽器該模組是 ES 模組。最後,雖然 CommonJS 預設使用 .js 副檔名,但您也可以使用 .mjs
評論留言