背景
まずは該当するjavascriptコードを確認しよう。自作jsモジュール notes.mjsからいくつかの関数をインポートしたかった。
import chalk from "chalk";
import yargs from "yargs";
import notes from "./notes.mjs"
yargs(process.argv.slice(2))
.usage('Usage: $0 <command> [options]')
.command('add', 'add note',
function (yargs) {
return yargs
.option('title', {
alias: 't',
default: '',
demandOption: true})
.option('body', {
alias: 'b',
default: '',
demandOption: true})
},
function(argv){
notes.addNotes(argv.title, argv.body)
// console.log(`Title: ${argv.title} Body: ${argv.title}`)
}
)
.example('$0 add --title hoge', 'add title "hoge"')
.help('h')
.alias('h', 'help')
.argv;
問題
しかしながら先ほどのjavascriptコードを実行しようとすると以下エラーが発生。
node app.mjs add --title hoge --body huga
file:///Users/user/node-js-basics/notes-app/app.mjs:3
import notes from "./notes.mjs"
^^^^^
SyntaxError: The requested module './notes.mjs' does not provide an export named 'default'
at ModuleJob._instantiate (node:internal/modules/esm/module_job:127:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:193:5)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:341:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)
Node.js v17.6.0
正直このシンタックスエラーの意味がよくわからなかった。「default」ってなんぞや・・・。
原因分析
自作javascriptモジュールがこちら。
import * as fs from 'fs'
import { add } from './utils.mjs'
const getNotes = function() {
return 'Your notes...'
}
export const addNotes = function(title, body) {
const notes = loadNotes()
console.log(notes)
}
const loadNotes = function() {
try {
const dataBuffer = fs.readFileSync('notes.json')
const dataJSON = JSON.toString(dataBuffer)
return JSON.parse(dataJSON)
} catch(e) {
return []
}
}
そこでjavascriptといえば我らがMDNドキュメントを見ると目から鱗。javascriptにおけるimportの構文を全く理解できていなかったことが発覚。
import defaultExport from "module-name";
import * as name from "module-name";
先述のjavascriptコードは上記の1行目と同じ表現になるがこちらは以下のように説明されている。
defaultExport:モジュールからのデフォルトのエクスポートを参照する名前。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import
つまりexport defaultで宣言したもののみがこの構文でimportできると理解(知らんけど)。
続いて2行目については以下のように説明されている。
name: インポートを参照するとき名前空間のように用いられるモジュールオブジェクトの名前。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import
つまりjavascriptでは任意のモジュールに含まれる要素を任意のオブジェクト名でimportするときはこの表現を使え、と理解(知らんけど)。
解決方法
冒頭のimprot文の表記をちょこっと変えただけ。
import chalk from "chalk";
import yargs from "yargs";
import * as notes from "./notes.mjs"