ค้นหาเว็บไซต์

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


ก่อนหน้านี้ babel จะเพิ่มบรรทัด 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 น้ำตา และวิธีแก้ไข

คำตอบ #1

ถ้าคุณต้องการพฤติกรรมการส่งออกแบบ 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}

คำตอบ #2

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

คำตอบ #3

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

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

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

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

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

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

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

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

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

บทความที่เกี่ยวข้อง