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 }; }
ฉันใช้เวลาหลายชั่วโมงต่อสู้กับเรื่องนี้ ดังนั้นฉันหวังว่าสิ่งนี้จะช่วยให้คนอื่นไม่ต้องเสียเวลาเหมือนฉัน!
