Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

@Kazunori-Kimura

Node.js(CommonJS)からECMAScript Moduleを読み込む

やりたいこと

Webアプリのbuild時にクライアントサイドの設定定義ファイル (ECMAScript Module形式) をビルドスクリプト (Node.jsのスクリプト、CommonJS) 内で読み込み、定義内容に応じた事前処理を実行したい。

フォルダ構成
project
  +- src               <- Reactのsrcフォルダ
  |   `- commons
  |        `- index.js <- このファイルが設定定義
  |
  `- scripts
      `- build.js      <- ビルド時の処理が書かれた Node.jsのスクリプト

問題点

  1. 通常の方法 (require) では CommonJS形式のスクリプトからECMAScript Module形式のファイルを呼び出すことはできない
  2. CommonJS形式のスクリプトではECMAScript Module形式の import/export は使用できない

CommonJSからECMAScript Moduleを取り込む方法

以下の手順を踏むと、 CommonJS から ECMAScript Module を取り込める

(1) ECMAScript Moduleの拡張子を .mjs とする

common.mjs
// ECMAScript Module
export const VERSION = '1.0.0';
export const config = {
  hoge: 'fuga',
  foo: 'bar',
};

(2) dynamic import を使用してimportする

index.js
// CommonJS
async function main() {
  // dynamic import
  const { config } = await import('./common.mjs');
  console.log(config);
}

main()
  .then(() => { console.log('done!'); })
  .catch((err) => { console.error(err); });

(3) nodeコマンドに --experimental-modulesフラグを指定する

$ node --experimental-modules index.js
(node:22431) ExperimentalWarning: The ESM module loader is experimental.
{ hoge: 'fuga', foo: 'bar' }
done!

まとめ

build.js の冒頭で src/commons/index.jsscripts/common.mjs にコピーし、そのファイルをimportすることでやりたいことが実現できた。

build.js
const path = require('path');
const fs = require('fs-extra');

async function main() {
  // 設定定義ファイル
  const commonFile = path.resolve(__dirname, '../src/commons/index.js');
  // .mjsファイル
  const commonMjs = path.resolve(__dirname, './common.mjs');
  // ファイルをコピー
  await fs.copyFile(commonFile, commonMjs);
  // dynamic import
  const { config } = await import(commonMjs);

  // ...以降ビルド処理をゴニョゴニョ...
}

main()
  .then(() => { console.log('done!'); })
  .catch((err) => { console.error(err); });

参考

Node.jsとECMAScript Modules - 技術探し
https://blog.hiroppy.me/entry/nodejs-esm

ECMAScript Modules | Node.js v11.0.0 Documentation
https://nodejs.org/api/esm.html

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What are the problem?