Hỗ trợ nhập ES6 trong mô-đun ES5


8

Đối với các sinh viên năm thứ nhất, tôi đã cung cấp một thư viện dựa trên ES5 đơn giản được viết bằng cách sử dụng Mô hình mô-đun tiết lộ. Đây là một đoạn của mô-đun / không gian tên "chính", sẽ chứa các phần mở rộng khác:

window.Library = (function ($) {
    if (!$) {
        alert("The Library is dependent on jQuery, which is not loaded!");
    }

    return {};
})(window.jQuery);

Điều này hoạt động với khá nhiều 99,9% sinh viên mới bắt đầu phát triển web và không sử dụng những thứ ưa thích như ES6 kết hợp với Webpack hoặc Babel.

0,1% hiện đã yêu cầu tôi cung cấp phiên bản dựa trên ES6, có thể được nhập chính xác. Tôi rất vui khi cung cấp điều này, nhưng tôi hơi bế tắc về cách tiếp cận tốt nhất với điều này.

Tôi rõ ràng muốn giữ cách ES5, vì vậy sinh viên của tôi chỉ có thể bao gồm tệp bằng cách sử dụng thẻ script và nhập bất cứ Library.SomeExtension.aFunction();nơi nào họ muốn. Trên hết, một số tiện ích mở rộng phụ thuộc vào jQuery, được thêm vào theo cách tương tự như đoạn trích ở trên.

Bây giờ tôi đang tìm kiếm một số cách có thể duy trì để tận dụng tốt nhất cả hai thế giới, với một cơ sở mã, với jQuery là một phụ thuộc. Tôi muốn cung cấp 99,9% a window.Library, trong khi tôi muốn cung cấp 0,1% cho cách sử dụng import Library from 'library'.

Tôi có thể thực hiện điều này với một tệp JS có cả hai không? Hoặc tôi sẽ cần một phiên bản ES6 đặc biệt (không phải là vấn đề để làm)? Và trên hết: Làm cách nào để tôi cải tổ mã của mình (tất cả tương tự như đoạn trích trên) theo cách tôi có thể hỗ trợ cả hai tình huống?

Bất kỳ và tất cả các con trỏ sẽ được đánh giá rất cao!

EDIT: Chỉ là một ghi chú bên lề, tôi đã có một gulpfile.jsvị trí điều hành thư viện này thông qua Babel, minifiersvà những thứ khác. Vì vậy, phải mở rộng điều đó để giải quyết vấn đề trên không phải là vấn đề!


Có lẽ giải quyết tốt nhất bằng cách sử dụng ES6 cho mình và bộ chuyển đổi / gói tạo ra mô-đun tiết lộ toàn cầu. Sau đó cung cấp mô-đun nguồn của bạn đến 0,1%. vì vậy, có, một tệp nguồn duy nhất, nhưng hai tệp được phân phối.
Bergi

Tôi hy vọng có câu trả lời cho Tôi có thể thực hiện điều này với một tệp JS duy nhất có cả hai không? - nếu điều này là có thể, mà nó có thể không, kịch bản sẽ trông như thế nào?
Tuyết

@Snow Hiện đang chơi xung quanh với các tài nguyên được cung cấp trong các câu trả lời. Phải dành thêm một chút thời gian để có được thứ gì đó tôi hài lòng, nhưng dường như có thể làm được nếu bạn có một chút sáng tạo khi xây dựng kịch bản của mình! Trong trường hợp cụ thể của tôi, tôi thực sự muốn giữ Library.SubLibrary.functionNamethiết lập và cả trong các tệp riêng biệt, ngay cả khi ai đó nhập nó dưới dạng ES6 hoặc bất cứ thứ gì khác. (Điều này chủ yếu là do các tiện ích mở rộng cũng có thể sử dụng lẫn nhau và sử dụng thiết lập ES6 tiêu chuẩn, điều này sẽ gây ra các tham chiếu vòng tròn).
Lennard Fonteijn

Đúng, thật đơn giản để thực hiện điều này bằng cách sử dụng các tệp riêng biệt: có một lần sử dụng exportvà có sự phân công khác window. Tôi đã nghĩ sẽ thật tuyệt nếu cả hai có thể được thực hiện trong một tệp duy nhất, vì điều đó sẽ cảm thấy thanh lịch hơn rất nhiều, nhưng exporttừ khóa dường như chỉ hoạt động bên trong a type=module. Tôi không biết nếu có một cách giải quyết, hoặc nếu điều đó là không thể.
Tuyết

@LennardFonteijn Các phụ thuộc tròn hoạt động hoàn toàn tốt với các mô-đun ES6, chỉ cần đảm bảo rằng bạn chỉ khai báo chức năng đã xuất và không chạy mã khởi tạo (phụ thuộc vào thứ tự đánh giá mô-đun) ở cấp cao nhất. Tôi khuyên bạn không nên sử dụng các đối tượng không gian tên lồng nhau, điều đó không phổ biến trong ES6.
Bergi

Câu trả lời:


5

Sau một vài đêm di chuyển mã xung quanh và cài đặt rất nhiều gói gulp tôi thậm chí không nhớ tất cả những gói tôi đã thử, cuối cùng tôi đã giải quyết được điều gì đó mà tôi rất hài lòng.

Đầu tiên, để trả lời câu hỏi của riêng tôi, cũng được @Bergi hỗ trợ trong các bình luận:

Câu trả lời ngắn: Không, bằng mọi cách (ngay bây giờ), trộn cú pháp ES6 với ES5 (mô-đun) trong một tệp duy nhất vì trình duyệt sẽ lỗi khi sử dụng export.

Câu trả lời dài: Về mặt kỹ thuật, bạn có thể đặt loại phần tử tập lệnh thành "mô-đun", điều này sẽ khiến các trình duyệt chấp nhận exporttừ khóa. Tuy nhiên, mã của bạn sẽ chỉ chạy hai lần (một lần khi tải và một lần sau khi nhập). Nếu bạn có thể sống với điều này, thì không trở thành có, kinda.

Vì vậy, cuối cùng tôi đã làm gì? Hãy để tôi đưa ra phía trước Tôi thực sự muốn giữ thiết lập Mô-đun IIFE tôi có (hiện tại) trong tệp ES5 đầu ra. Tôi đã cập nhật cơ sở mã của mình thành ES6 thuần túy và đã thử tất cả các loại kết hợp bổ trợ (bao gồm cả Rollup.js được đề cập bởi @David Bradshaw). Nhưng tôi chỉ đơn giản là không thể làm cho chúng hoạt động được, hoặc chúng sẽ xử lý hoàn toàn đầu ra theo cách mà các trình duyệt không thể tải mô-đun nữa hoặc bỏ hỗ trợ sourcemap. Với dự án mà các sinh viên đang thực hiện sắp kết thúc, tôi đã lãng phí đủ thời gian rảnh rỗi của mình cho 0,1% sinh viên của mình. Vì vậy, may mắn hơn trong năm tới cho một giải pháp "đẹp hơn".

  1. Tôi đã dựa trên mẫu UMD của mình (như được đề cập bởi @Sly_cardinal) trên jQuery và ném mã đó vào a Library.umd.js. Đối với phần ES6, tôi đã thực hiện Library.es6.jschỉ với một export default Librarytrong đó.

  2. Trong cả hai tệp, tôi đã đặt một nhận xét nhiều dòng /*[Library.js]*/trong đó tôi muốn tiêm Library.js chưa được rút gọn.

  3. Tôi sửa đổi nhiệm vụ Gulp hiện tại của tôi chỉ xây dựng Library.jsvới concatBabelvà lưu trữ nó trên một vị trí tạm thời. Tôi đã chọn hy sinh hỗ trợ bản đồ nguồn trong quá trình này, vì mã được nối hoàn toàn có thể đọc được ở đầu ra. Kỹ thuật hỗ trợ bản đồ nguồn "hoạt động", nhưng nó vẫn sẽ loại bỏ trình gỡ lỗi quá nhiều.

  4. Tôi đã thêm một tác vụ Gulp bổ sung để đọc nội dung của temp Library.js, sau đó với mỗi tệp từ Bước 1, tôi sẽ tìm và thay thế nhận xét nhiều dòng bằng nội dung. Lưu các tệp kết quả và sau đó ném chúng qua phần cuối cùng concat(ví dụ: gói với jQuery) terservà tạo sơ đồ chua.

Kết quả cuối cùng là hai tệp:

  • Một hỗ trợ trình duyệt UMD / ES5
  • Một hỗ trợ ES6

Mặc dù tôi hài lòng với kết quả này, tôi không thích chuỗi nhiệm vụ Gulp và mất hỗ trợ sourcemap trong nửa đầu của quy trình. Như đã nói trước đó, tôi đã thử nhiều plugin gulp để đạt được hiệu quả tương tự (ví dụ gulp-inject), nhưng chúng không hoạt động đúng hoặc làm những điều kỳ lạ với sourcemap (ngay cả khi chúng tuyên bố hỗ trợ nó).

Đối với một nỗ lực tiếp theo, tôi có thể xem xét một cái gì đó khác với Gulp, hoặc sử dụng plugin của riêng tôi, nhưng thực hiện đúng cách: P


0

Bạn có thể sử dụng Rollup.js để gói mã của mình dưới dạng thư viện ES5 cũng như mô-đun ES6 đi kèm.

Rollup đã tích hợp hỗ trợ cho Gulp nên một cái gì đó như thế này sẽ là điểm khởi đầu hợp lý (dựa trên ví dụ Gulp của Rollup):

    const gulp = require('gulp');
    const rollup = require('rollup');
    const rollupTypescript = require('rollup-plugin-typescript');

    gulp.task('bundle', () => {
      return rollup.rollup({
        input: './src/main.ts',
        plugins: [
          rollupTypescript()
        ]
      }).then(bundle => {
          return Promise.all([
              // Build for ES5
              bundle.write({
                file: './dist/library.js',
                format: 'umd',
                name: 'Library',
                sourcemap: true
            }),

            // Build for ES6 modules
            bundle.write({
                file: './dist/library.esm.js',
                format: 'esm',
                sourcemap: true
            })
          ]);
      });
    });

Bạn có thể xem thêm thông tin về các định dạng đầu ra khác nhau có sẵn: https://rollupjs.org/guide/en/#outputformat

Nói chung là dễ nhất nếu nguồn thư viện của bạn được viết bằng các mô-đun ES và sau đó được gói / dịch mã xuống gói ES5.


Điều này trông tuyệt vời và chính xác những gì tôi cần! Sẽ quay nó và báo cáo lại :)
Lennard Fonteijn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.