javascript - Làm thế nào để TypeScript xuất ra các câu lệnh import module ES6 hợp lệ?
Tất cả các trình duyệt chính đã hỗ trợ các module ES6 từ một thời gian trước.
Chúng khác với nhiều phương pháp phía máy chủ ở chỗ chúng cần chỉ định chính xác tệp để nhập - chúng không thể sử dụng khám phá tệp.
Điều này có lý - trong các ứng dụng Node hoặc các bộ đóng gói như WebPack, họ thực sự chỉ cần tên của module, và sau đó có thể dành thêm chút thời gian để tìm ra tệp cụ thể chứa mã. Trên web, điều đó có thể gây lãng phí nhiều lượt truy cập (liệu 'library' có ở library/index.js, hay library/library.js, hay library.js? require() không quan tâm nhưng trên web chúng ta phải quan tâm).
TypeScript có hỗ trợ các module ES6 (đặt "module": "es6" trong tsconfig.json) nhưng có vẻ như nó đang sử dụng một phương pháp khám phá tệp...
Giả sử tôi có library.ts:
export function myFunction(...) { ... }
Sau đó trong app.ts:
import {myFunction} from './library';
var x = myFunction(...);
Tuy nhiên, điều này không thay đổi khi biên dịch - đầu ra TS vẫn có tên 'library' để phát hiện tệp, điều này không hoạt động. Điều này gây ra lỗi vì 'library' không được tìm thấy:
<script type="module" src="app.js"></script>
Để các module ES6 hoạt động, đầu ra TS cần tham chiếu đến tệp cụ thể:
import {myFunction} from './library.js';
var x = myFunction(...);
Làm thế nào để tôi khiến TS xuất ra các câu lệnh import của module ES6 hợp lệ?
Lưu ý: Tôi không hỏi cách để một trình đóng gói ghép đầu ra TS thành một tệp duy nhất. Tôi muốn tải từng tệp này riêng lẻ bằng <script type="module">
Câu trả lời #1
Đây là một lỗi trong TypeScript, mặc dù có một số tranh cãi về việc liệu nó có nên được sửa hay không.
Có một cách giải quyết: trong khi TS sẽ không cho phép bạn chỉ định một tệp .ts làm nguồn của một mô-đun, nó sẽ cho phép bạn chỉ định phần mở rộng .js (và sau đó bỏ qua nó).
Vậy trong app.ts:
import {myFunction} from './library.js';
var x = myFunction(...);
Điều này sau đó xuất ra đúng trong app.js, và TS đã tìm thấy các định nghĩa và liên kết import một cách chính xác.
Điều này có một lợi thế/lưu ý cần nhận thức/cẩn thận: TS chỉ bỏ qua phần mở rộng .js và tải phần còn lại của đường dẫn với cơ chế tìm tệp thông thường. Điều này có nghĩa là nó sẽ import library.ts, nhưng nó cũng có thể tìm thấy các tệp định nghĩa như library.d.ts hoặc các tệp import trong một thư mục library/.
Trường hợp cuối cùng đó có thể là mong muốn nếu bạn đang ghép những tệp đó lại thành một đầu ra library.js, nhưng để làm điều đó, bạn sẽ phải xem xét hoặc rất nhiều tệp tsconfig.json lồng nhau (lộn xộn) hoặc có thể là đầu ra đã được tiền chuyển đổi của một thư viện khác.
Câu trả lời #2
Bộ biên dịch nhận một cờ loại mô-đun:
--module ES2015
Và bạn cũng sẽ cần nhắm mục tiêu ECMAScript 6/2015...
--target ES2015
Bạn cần cả loại mô-đun và mục tiêu biên dịch phải là ECMAScript 2015 trở lên để có "nhập khẩu không biến đổi".
Các câu lệnh nhập khẩu của bạn nên trông ở giữa hai ví dụ của bạn:
import {myFunction} from './library';
Ghi chú bổ sung
Vẫn còn rõ ràng rất nhiều cuộc thảo luận về việc giải quyết module... có tiêu chuẩn TC39, và tiêu chuẩn WHATWG - cộng với Node hiện tại vẫn chưa có phần mở rộng tệp... có vẻ như RequireJS có thể tồn tại lâu hơn chúng ta tưởng... vui lòng xem:
Chuỗi TypeScript để hỗ trợ phần mở rộng tệp trong quá trình biên dịch khi import (tức là, nó có thêm phần mở rộng tệp không?).
Khuyến nghị
Gắn bó với một bộ nạp module, ví dụ RequireJS hoặc SystemJS. Điều này cũng có nghĩa là các module của bạn có thể được chia sẻ giữa trình duyệt và máy chủ bằng cách sử dụng các loại module UMD hoặc System tương ứng.
Rõ ràng, một khi cuộc thảo luận về ECMAScript đi đến kết luận, điều này sẽ cần được xem xét lại.
