Babel 6 mengubah cara ekspor default

195

Sebelumnya, babel akan menambahkan baris module.exports = exports["default"]. Tidak lagi melakukan ini. Apa artinya ini sebelum saya bisa melakukan:

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

Sekarang saya harus melakukan ini:

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

Bukan masalah besar (dan saya menduga inilah yang seharusnya selama ini). Masalahnya adalah bahwa saya memiliki banyak kode yang bergantung pada cara hal-hal yang digunakan untuk bekerja (saya dapat mengonversikan sebagian besar ke impor ES6, tetapi tidak semuanya). Adakah yang bisa memberi saya tips tentang cara membuat cara lama bekerja tanpa harus melalui proyek saya dan memperbaiki ini (atau bahkan beberapa instruksi tentang cara menulis codemod untuk melakukan ini akan sangat licin).

Terima kasih!

Contoh:

Memasukkan:

const foo = {}
export default foo

Output dengan Babel 5

"use strict";

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

Output dengan Babel 6 (dan plugin es2015):

"use strict";

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

Perhatikan bahwa satu-satunya perbedaan dalam output adalah module.exports = exports["default"].


Edit

Anda mungkin tertarik pada posting blog ini yang saya tulis setelah menyelesaikan masalah spesifik saya: Modul ES6 Kesalahpahaman, Memutakhirkan Babel, Air Mata, dan Solusi

kentcdodds
sumber
Saya ingin tahu, kasus-kasus apa yang dibutuhkan requirejika Anda bekerja dalam basis kode yang menggunakan Babel? Kemungkinannya, ada beberapa pendekatan lain yang memungkinkan Anda untuk menghindarinya.
loganfsmyth
Saya menggunakan fitur Webpack yang tidak memerlukan kode jika ditemukan dalam kode mati seperti: if (false) { require('./foo') }dengan webpack akan melompati sebenarnya termasuk foo.jsdalam bundel yang dihasilkan.
kentcdodds
Apa yang akhirnya menjadi falsetoggle Anda di sana? Jika itu adalah kondisi yang tersedia di konfigurasi webpack Anda, mungkin ada opsi lain.
loganfsmyth
Yang ini juga menggigitku. Terima kasih @kentcdodds.
Tyler McGinnis
1
Yang ini menyebabkan masalah selama berjam-jam sebelum saya menemukan posting ini. Saya akhirnya mengganti semua export default {foo, bar}dengan saya module.exports = {foo, bar}. Saya cukup menyukai metode yang salah yang sekarang tidak didukung.
stumct

Jawaban:

90

Anda juga dapat menggunakan plugin ini untuk mendapatkan exportkembali perilaku lama .

SimenB
sumber
1
Saya tahu seseorang akan menulis sebuah plugin untuk cepat atau lambat. Terima kasih!
kentcdodds
sayangnya babel-plugin-add-module-ekspor tidak mendukung modul-gaya amd (belum)
zower
3
Saya telah menggunakan babel-plugin-transform-es2015-modules-simple-amd untuk menyelesaikan masalah yang sama ini di proyek saya yang memiliki modul AMD
Tom Wayson
Saya pikir menggunakan UMD dan plugin ini adalah cara untuk pergi! Terima kasih
electronix384128
Sangat sangat membantu
Jovica Aleksic
105

Jika Anda ingin perilaku ekspor CommonJS, Anda harus menggunakan CommonJS secara langsung (atau menggunakan plugin di jawaban lain). Perilaku ini telah dihapus karena menyebabkan kebingungan dan menyebabkan semantik ES6 yang tidak valid, yang diandalkan oleh beberapa orang misalnya

export default {
  a: 'foo'
};

lalu

import {a} from './foo';

yang ES6 tidak valid tetapi bekerja karena perilaku interoperabilitas CommonJS yang Anda gambarkan. Sayangnya mendukung kedua kasus itu tidak mungkin, dan memungkinkan orang untuk menulis ES6 yang tidak valid adalah masalah yang lebih buruk daripada membuat Anda melakukannya .default.

Masalah lainnya adalah bahwa itu tidak terduga bagi pengguna jika mereka menambahkan ekspor bernama di masa depan, misalnya

export default 4;

kemudian

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

tapi

export default 4;
export var foo = 5;

kemudian

require('./mod')
// {'default': 4, foo: 5}
loganfsmyth
sumber
Saya setuju dengan Anda (dan mencatat) bahwa perilaku sebelumnya tidak benar, tetapi pertanyaan saya adalah bagaimana menyiasatinya. Saya sangat bergantung pada perilaku yang salah (tidak menyadari itu salah sampai pagi ini). Saya lebih suka tidak harus memperbarui semuanya sekaligus ...
kentcdodds
Satu-satunya perbaikan untuk mendapatkan perilaku saat ini adalah mengganti kode Anda untuk menggunakan CommonJS secara langsung, atau tetap menggunakan Babel 5 hingga Anda punya waktu untuk memperbarui.
loganfsmyth
4
@kentcdodds kita dapat menulis loader webpack agar tetap berfungsi (atau plugin babel). Saya terkejut mereka tidak menyediakan satu (atau mempublikasikan perubahan lebih berat!)
Jamund Ferguson 3-15
Saya bingung dengan ini ... jika saya melakukannya export default function () {}di modul A dan kemudian import a from 'a'di modul B, dengan Babel 6 aakan menjadi { default: function () {} }... Dari apa yang saya bisa pahami dari explorejs.com/es6/… ini seharusnya bekerja dan saya harus mendapatkan hasil ekspor fungsi dalam B, bukan objek.
mamapitufo
@ mamapitufo Itu seharusnya berhasil, tetapi sulit untuk mengatakan apa yang salah tanpa contoh untuk dilihat. Silakan mampir di saluran dukungan Babel di Slack jika Anda ingin mengobrol.
loganfsmyth
33

Untuk penulis perpustakaan, Anda mungkin dapat mengatasi masalah ini.

Saya biasanya memiliki titik masuk index.js,, yang merupakan file yang saya tunjuk dari bidang utama di package.json. Ia tidak melakukan apa-apa selain mengekspor kembali titik masuk aktual lib:

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

Untuk mengatasi masalah babel, saya mengubah ini menjadi importpernyataan dan kemudian menetapkan default ke module.exports:

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

Semua file saya yang lain tetap sebagai modul ES6 murni, tanpa solusi. Jadi hanya titik masuk yang perlu diubah sedikit :)

Ini akan bekerja untuk commonjs memerlukan, dan juga untuk impor ES6 karena babel tampaknya tidak menjatuhkan reverse interop (commonjs -> es6). Babel menyuntikkan fungsi berikut untuk menambal commonjs:

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

Saya telah menghabiskan berjam-jam berjuang melawan ini, jadi saya harap ini menyelamatkan orang lain upaya!

WickyNilliams
sumber
Untuk beberapa alasan, kepala saya tidak pernah diputar dengan benar module.exportsdan export defaultsebagainya. Sekarang kita kembali ke titik awal?
windmaomao
@windmaomao apa maksudmu? Ini adalah trik agar pengguna biasa tidak harus melakukannya require("whatever").default. Jika Anda bukan penulis perpustakaan, ini mungkin tidak relevan
WickyNilliams
1

Saya memiliki masalah seperti itu. Dan ini solusi saya:

//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);
Ihor Pavlyk
sumber