Babel 6 thay đổi cách xuất mặc định


195

Trước đây, babel sẽ thêm dòng module.exports = exports["default"]. Nó không còn làm điều này. Điều này có nghĩa là trước khi tôi có thể làm:

var foo = require('./foo');
// use foo

Bây giờ tôi phải làm điều này:

var foo = require('./foo').default;
// use foo

Không phải là một vấn đề lớn (và tôi đoán đây là những gì nó nên có cùng). Vấn đề là tôi có rất nhiều mã phụ thuộc vào cách mọi thứ hoạt động (tôi có thể chuyển đổi hầu hết mã sang nhập ES6, nhưng không phải tất cả mã). Bất cứ ai có thể cho tôi lời khuyên về cách làm cho cách cũ hoạt động mà không cần phải thông qua dự án của tôi và sửa lỗi này (hoặc thậm chí một số hướng dẫn về cách viết một codemod để làm điều này sẽ khá khó khăn).

Cảm ơn!

Thí dụ:

Đầu vào:

const foo = {}
export default foo

Đầu ra với Babel 5

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var foo = {};
exports["default"] = foo;
module.exports = exports["default"];

Đầu ra với Babel 6 (và plugin es2015):

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var foo = {};
exports["default"] = foo;

Lưu ý rằng sự khác biệt duy nhất trong đầu ra là module.exports = exports["default"].


Biên tập

Bạn có thể quan tâm đến blog này tôi đã viết sau khi giải quyết vấn đề cụ thể của mình: Hiểu lầm Mô-đun ES6, Nâng cấp Babel, Nước mắt và Giải pháp


Tôi tò mò, những trường hợp cần thiết requirenếu bạn đang làm việc trong một cơ sở mã sử dụng Babel là gì? Rất có thể, có những cách tiếp cận khác sẽ cho phép bạn tránh điều đó bằng mọi cách.
loganfsmyth

Tôi đang tận dụng một tính năng của Webpack sẽ không yêu cầu mã nếu nó được tìm thấy trong mã chết như: if (false) { require('./foo') }với webpack sẽ bỏ qua thực sự bao gồm foo.jstrong gói kết quả.
kentcdodds

Điều gì kết thúc là sự falsechuyển đổi của bạn ở đó? Nếu đó là một điều kiện có sẵn trong cấu hình gói web của bạn, có thể có một tùy chọn khác.
loganfsmyth

Cái này một chút tôi cũng vậy. Cảm ơn @kentcdodds.
Tyler McGinnis

1
Điều này gây ra cho tôi các vấn đề trong nhiều giờ trước khi tôi tìm thấy bài viết này. Tôi cuối cùng đã thay thế tất cả của tôi export default {foo, bar}với module.exports = {foo, bar}. Tôi khá thích phương pháp không chính xác mà bây giờ không được hỗ trợ.
stumct

Câu trả lời:


90

Bạn cũng có thể sử dụng plugin này để lấy exportlại hành vi cũ .


1
Tôi biết ai đó sẽ viết một plugin cho sớm hay muộn. Cảm ơn!
kentcdodds

đáng buồn là babel-plugin-add-module-export không hỗ trợ các mô-đun kiểu amd (chưa)
zowers

3
Tôi đã sử dụng babel-plugin-Transform-es2015-mô-đun-đơn giản-amd để giải quyết vấn đề tương tự trong dự án của tôi có các mô-đun AMD
Tom tiết lộ

Tôi nghĩ rằng sử dụng UMD và plugin này là cách tốt nhất! Cảm ơn
electronix384128

Rất rất hữu ích.
Jovica Aleksic

105

Nếu bạn muốn hành vi xuất CommonJS, bạn sẽ cần sử dụng CommonJS trực tiếp (hoặc sử dụng plugin trong câu trả lời khác). Hành vi này đã bị xóa vì nó gây nhầm lẫn và dẫn đến ngữ nghĩa ES6 không hợp lệ, mà một số người đã dựa vào, ví dụ

export default {
  a: 'foo'
};

và sau đó

import {a} from './foo';

ES6 không hợp lệ nhưng hoạt động được do hành vi tương tác CommonJS mà bạn đang mô tả. Thật không may, hỗ trợ cả hai trường hợp là không thể và cho phép mọi người viết ES6 không hợp lệ là một vấn đề tồi tệ hơn so với việc bạn làm .default.

Vấn đề khác là nó gây bất ngờ cho người dùng nếu họ thêm một xuất khẩu có tên trong tương lai, ví dụ

export default 4;

sau đó

require('./mod');
// 4

nhưng

export default 4;
export var foo = 5;

sau đó

require('./mod')
// {'default': 4, foo: 5}

Tôi đồng ý với bạn (và lưu ý) rằng hành vi trước đó là không chính xác, nhưng câu hỏi của tôi là làm thế nào để giải quyết vấn đề. Tôi đã phụ thuộc rất nhiều vào hành vi không đúng (không nhận ra điều đó là không đúng cho đến sáng nay). Tôi muốn không phải cập nhật tất cả mọi thứ cùng một lúc ...
kentcdodds

Cách khắc phục duy nhất để có được hành vi hiện tại là chuyển mã của bạn sang sử dụng CommonJS trực tiếp hoặc ở lại Babel 5 cho đến khi bạn có thời gian cập nhật.
loganfsmyth

4
@kentcdodds chúng ta có thể viết một trình tải webpack để duy trì hoạt động này (hoặc một plugin babel). Tôi ngạc nhiên khi họ không cung cấp một (hoặc công khai thay đổi nặng nề hơn!)
Jamund Ferguson

Tôi bối rối bởi điều này ... nếu tôi làm export default function () {}trong mô-đun A và sau đó import a from 'a'trong mô-đun B, với Babel 6 asẽ { default: function () {} }... Từ những gì tôi có thể hiểu được từ exploringjs.com/es6/... này nên làm việc và tôi sẽ nhận được xuất khẩu hàm trong B, không phải đối tượng.
mamapitufo

@mamapitufo Điều đó sẽ hiệu quả, nhưng thật khó để nói những gì sai mà không có ví dụ để xem xét. Hãy ghé qua kênh hỗ trợ của Babel trên Slack nếu bạn muốn trò chuyện.
loganfsmyth

33

Đối với các tác giả thư viện, bạn có thể giải quyết vấn đề này.

Tôi thường có một điểm vào index.js, đó là tệp tôi trỏ đến từ trường chính trong package.json. Nó không làm gì khác hơn là tái xuất điểm nhập thực tế của lib:

export { default } from "./components/MyComponent";

Để khắc phục sự cố babel, tôi đã thay đổi điều này thành một importcâu lệnh và sau đó gán mặc định cho module.exports:

import MyComponent from "./components/MyComponent";
module.exports = MyComponent;

Tất cả các tệp khác của tôi ở dạng mô-đun ES6 thuần túy, không có cách giải quyết. Vì vậy, chỉ có điểm vào cần một chút thay đổi :)

Điều này sẽ hoạt động cho các yêu cầu chung và cả nhập khẩu ES6 vì babel dường như không bỏ qua phần đảo ngược (commonjs -> es6). Babel tiêm các chức năng sau để vá lỗi chung:

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 

Tôi đã dành hàng giờ để chiến đấu với điều này, vì vậy tôi hy vọng điều này sẽ giúp người khác nỗ lực!


Đối với một số lý do, tôi không bao giờ đứng đầu của tôi spinned đúng về module.exportsexport defaultcông cụ. Bây giờ chúng ta quay lại quảng trường?
Windmaomao

@windmaomao có nghĩa là gì? Đây là một mẹo để người dùng thường không phải làm vậy require("whatever").default. Nếu bạn không phải là tác giả thư viện, điều này có lẽ không liên quan
WickyNilliams

1

Tôi đã có loại vấn đề như vậy. Và đây là giải pháp của tôi:

// src/arithatures.js

export var operations = {
  add: function (a, b) {
      return a + b;
  },

  subtract: function (a, b) {
      return a - b;
  }
};

//src/main.js

import { operations }  from './arithmetic';

let result = operations.add(1, 1);

console.log(result);
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.