Babel 6 เปลี่ยนวิธีการส่งออกเริ่มต้น


195

module.exports = exports["default"]ก่อนที่บาเบลจะเพิ่มบรรทัด มันไม่ทำเช่นนี้อีกต่อไป สิ่งนี้หมายความว่าอย่างไรก่อนที่ฉันจะทำ:

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

ตอนนี้ฉันต้องทำสิ่งนี้:

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

ไม่ใช่เรื่องใหญ่โต (และฉันเดาว่านี่คือสิ่งที่ควรจะเป็นมาตลอด) ปัญหาคือฉันมีรหัสจำนวนมากซึ่งขึ้นอยู่กับวิธีการใช้งาน (ฉันสามารถแปลงส่วนใหญ่เป็นการนำเข้า ES6 แต่ไม่ใช่ทั้งหมด) ทุกคนสามารถให้คำแนะนำเกี่ยวกับวิธีการทำงานแบบเก่าโดยไม่ต้องผ่านโครงการของฉันและแก้ไขปัญหานี้ (หรือแม้แต่คำแนะนำในการเขียน codemod เพื่อทำสิ่งนี้จะค่อนข้างลื่น)

ขอบคุณ!

ตัวอย่าง:

การป้อนข้อมูล:

const foo = {}
export default foo

ผลลัพธ์ด้วย Babel 5

"use strict";

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

เอาต์พุตด้วย Babel 6 (และปลั๊กอิน es2015):

"use strict";

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

module.exports = exports["default"]ขอให้สังเกตว่าที่แตกต่างในการส่งออกเป็น


แก้ไข

คุณอาจสนใจในบล็อกนี้ฉันเขียนหลังจากแก้ปัญหาเฉพาะของฉัน: โมดูล ES6 ที่เข้าใจผิด, การอัพเกรด Babel, Tears และ Solution


ฉันอยากรู้อยากเห็นอะไรที่requireคุณจำเป็นต้องใช้ถ้าคุณทำงานใน codebase ที่ใช้ Babel? โอกาสที่จะมีวิธีการอื่น ๆ ที่จะช่วยให้คุณสามารถหลีกเลี่ยงได้
loganfsmyth

ฉันใช้ประโยชน์จากคุณสมบัติของ Webpack ซึ่งจะไม่ต้องใช้รหัสหากพบในรหัสที่ตายแล้วเช่น: if (false) { require('./foo') }ด้วย webpack จะข้ามจริง ๆ รวมถึงfoo.jsในกลุ่มผลลัพธ์
kentcdodds

อะไรคือการfalseสลับของคุณที่นั่น? หากเป็นเงื่อนไขที่มีอยู่ในการกำหนดค่า webpack ของคุณอาจมีตัวเลือกอื่น
loganfsmyth

อันนี้ก็กัดฉันด้วย ขอบคุณ @ kentcdodds
Tyler McGinnis

1
อันนี้ทำให้ฉันมีปัญหาหลายชั่วโมงก่อนที่ฉันจะพบโพสต์นี้ ฉันสิ้นสุดขึ้นแทนที่ทั้งหมดของฉันด้วยexport default {foo, bar} module.exports = {foo, bar}ฉันค่อนข้างชอบวิธีที่ไม่ถูกต้องซึ่งตอนนี้ไม่ได้รับการสนับสนุน
หยุดชะงัก

คำตอบ:


90

คุณยังสามารถใช้ปลั๊กอินนี้เพื่อทำให้exportพฤติกรรมเก่ากลับมา


1
ฉันรู้ว่าบางคนจะเขียนปลั๊กอินไม่ช้าก็เร็ว ขอบคุณ!
kentcdodds

น่าเศร้า babel-plugin-add-module-exports ไม่รองรับโมดูลสไตล์เอเอ็มดี (ยัง)
58

3
ฉันใช้Babel-ปลั๊กอินเปลี่ยน-es2015 โมดูลง่าย-เอเอ็มดีในการแก้ปัญหาเดียวกันนี้ในโครงการของฉันที่มีโมดูลเอเอ็มดี
ทอม Wayson

ฉันคิดว่าใช้ UMD และปลั๊กอินนี้เป็นวิธีที่จะไป! ขอบคุณ
electronix384128

มีประโยชน์มาก ๆ
Jovica Aleksic

105

หากคุณต้องการพฤติกรรมการส่งออกของ CommonJS คุณจะต้องใช้ CommonJS โดยตรง (หรือใช้ปลั๊กอินในคำตอบอื่น ๆ ) พฤติกรรมนี้ถูกลบออกเพราะทำให้เกิดความสับสนและนำไปสู่ความหมายที่ไม่ถูกต้องของ ES6 ซึ่งบางคนอาศัยเช่น

export default {
  a: 'foo'
};

แล้ว

import {a} from './foo';

ซึ่ง ES6 ไม่ถูกต้อง แต่ทำงานได้เนื่องจากพฤติกรรมการทำงานร่วมกันของ CommonJS ที่คุณกำลังอธิบาย แต่น่าเสียดายที่สนับสนุนทั้งสองกรณีเป็นไปไม่ได้และช่วยให้คนที่จะเขียนไม่ถูกต้อง ES6 .defaultเป็นปัญหาที่เลวร้ายยิ่งกว่าการที่คุณทำ

ปัญหาอื่นคือผู้ใช้ไม่คาดคิดหากพวกเขาเพิ่มการส่งออกที่มีชื่อในอนาคตเช่น

export default 4;

แล้วก็

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

แต่

export default 4;
export var foo = 5;

แล้วก็

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

ฉันเห็นด้วยกับคุณ (และบันทึกไว้) ว่าพฤติกรรมก่อนหน้านี้ไม่ถูกต้อง แต่คำถามของฉันคือวิธีการแก้ไขปัญหา ฉันพึ่งพาพฤติกรรมที่ไม่ถูกต้องเป็นอย่างมาก (ไม่รู้เลยว่ามันไม่ถูกต้องจนถึงเช้านี้) ฉันต้องการที่จะไม่ต้องอัปเดตทุกอย่างในครั้งเดียว ...
kentcdodds

การแก้ไขปัญหาเพียงอย่างเดียวเพื่อให้ได้รับพฤติกรรมในปัจจุบันจะเป็นการสลับรหัสของคุณเพื่อใช้ CommonJS โดยตรงหรืออยู่ใน Babel 5 จนกว่าคุณจะมีเวลาอัปเดต
loganfsmyth

4
@ kentcdodds เราสามารถเขียน webpack loader เพื่อให้การทำงานนี้ (หรือปลั๊กอินของ babel) ฉันประหลาดใจที่พวกเขาไม่ได้ให้บริการหนึ่ง (หรือเผยแพร่การเปลี่ยนแปลงอย่างหนักมากขึ้น!)
Jamund Ferguson

ฉันสับสนกับสิ่งนี้ ... ถ้าฉันทำexport default function () {}ในโมดูล A และจากนั้นimport a from 'a'ในโมดูล B โดยที่ Babel 6 aจะเป็น{ default: function () {} }... จากสิ่งที่ฉันสามารถเข้าใจได้จากsurveyjs.com/es6/…สิ่งนี้ควรใช้ได้และฉันควรได้รับการส่งออก ฟังก์ชั่นใน B ไม่ใช่วัตถุ
mamapitufo

@amapitufo มันควรจะใช้ได้ แต่ก็ยากที่จะพูดว่ามีอะไรผิดปกติโดยไม่มีตัวอย่างให้ดู อย่าลังเลที่จะแวะไปที่ช่องสนับสนุนของ Babel บน Slack หากคุณต้องการแชท
loganfsmyth

33

สำหรับผู้เขียนห้องสมุดคุณอาจแก้ไขปัญหานี้ได้

ฉันมักจะมีจุดเริ่มต้นที่ซึ่งเป็นจุดไฟล์ฉันไปจากสนามหลักในindex.js package.jsonไม่ทำอะไรเลยนอกจากส่งออกจุดเข้าใช้งานจริงของ lib อีกครั้ง:

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

เพื่อแก้ไขปัญหาเกี่ยวกับ Babel ฉันเปลี่ยนสิ่งนี้เป็นimportคำสั่งแล้วกำหนดค่าเริ่มต้นเป็นmodule.exports:

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

ไฟล์อื่น ๆ ของฉันยังคงเป็นโมดูล ES6 แท้ๆโดยไม่มีวิธีแก้ไข ดังนั้นจุดเข้าใช้งานต้องมีการเปลี่ยนแปลงเล็กน้อย :)

สิ่งนี้จะใช้ได้กับ commonjs ที่ต้องการและสำหรับการนำเข้า ES6 เพราะดูเหมือนว่า Babel จะไม่ได้ลดการเชื่อมต่อแบบย้อนกลับ (commonjs -> es6) Babel ฉีดฟังก์ชันต่อไปนี้เพื่อแก้ไข commonjs:

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

ฉันใช้เวลาหลายชั่วโมงในการต่อสู้กับสิ่งนี้ดังนั้นฉันหวังว่าสิ่งนี้จะช่วยคนอื่นได้อีก!


ด้วยเหตุผลบางอย่างฉันไม่เคยมีหัวของฉันหมุนไปรอบๆmodule.exportsและexport defaultสิ่งของ ทีนี้เรากลับไปที่จตุรัส
windmaomao

@windmaomao คุณหมายถึงอะไร นี่คือเคล็ดลับเพื่อให้ผู้ใช้ commonjs require("whatever").defaultไม่ต้อง หากคุณไม่ใช่ผู้เขียนห้องสมุดนี่อาจไม่เกี่ยวข้องเลย
WickyNilliams

1

ฉันมีปัญหาแบบนี้ และนี่คือทางออกของฉัน:

//src/arithmetic.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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.