水が入った紙コップを火にかけるとどうなる?
レシピを見ないで上手にスライムを作れるのは誰だ?
最強の車を作れるのは誰だ?〜車台編



@akamiharamiさんからの提案でした!
メンバーのakamiharamiさんがデザイン・制作してくれました。どうもありがとうございます。ウェブサイトのサイドバーにてお客様をお出迎えしてくれます^^
まずは該当コードを確認しよう。自作モジュール 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;
しかしながらこのコードを実行しようとすると以下エラーが発生。
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」ってなんぞや・・・。
ちなみに自作モジュールがこちら。
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 []
}
}
そこで我らがMDNドキュメントを見ると目から鱗。importの構文を全く理解できていなかったことが発覚。
import defaultExport from "module-name";
import * as name from "module-name";
先述のコードは上記の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
つまり任意のモジュールに含まれる要素を任意のオブジェクト名でimportするときはこの表現を使え、と理解(知らんけど)。
冒頭のimprot文の表記をちょこっと変えただけ。
import chalk from "chalk";
import yargs from "yargs";
import * as notes from "./notes.mjs"
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export
https://www.npmjs.com/package/yargs
https://www.npmjs.com/package/yargs-parser
yargsがyargs-parserを包括している感じでしょうか?実際の挙動を見てみます。
import yargsp from "yargs-parser";
import yargs from "yargs";
import process from "process";
console.log(yargs(process.argv.slice(2)));
console.log(yargs(process.argv.slice(2)).argv);
console.log(yargsp(process.argv.slice(2)));
$ node app.mjs add --title="Things to buy"
YargsInstance {
customScriptName: false,
parsed: false,
'$0': 'app-chap16.mjs',
argv: [Getter]
}
{ _: [ 'add' ], title: 'Things to buy', '$0': 'app-chap16.mjs' }
{ _: [ 'add' ], title: 'Things to buy' }
コマンドラインからコマンドをパースさせます。
yargs(process.argv.slice(2))
.usage('Usage: $0 <command> [options]')
.command('count', 'Count the files in a directory', function (yargs) {
console.log('count items!')
})
.command('list', 'list files of a directory:', function (yargs) {
console.log('list items!')
})
.example('$0 count', 'count the lines in the given file')
.help('h')
.alias('h', 'help')
.argv;
以下のコマンドを実行します。想定通りの結果になっているでしょうか?
$ node app.mjs count
count items!
$ node app.mjs list
list items!
$ node app.mjs --help
Usage: app.mjs <command> [options]
Commands:
app.mjs count Count the files in a directory
app.mjs list list files of a directory:
Options:
--version Show version number [boolean]
-h, --help Show help [boolean]
Examples:
app.mjs count count the lines in the given file
countやlistといったコマンドにオプションを追加してやります。以前はbuilderとしてオプションを与えていたみたいですが・・・。
yargs(process.argv.slice(2))
.usage('Usage: $0 <command> [options]')
.command('count', 'Count the files in a directory', function (yargs) {
return yargs.option('directory', {
alias: 'd',
default: './'
})
console.log('count items!')
})
.command('list', 'list files of a directory:', function (yargs) {
return yargs.option('directory', {
alias: 'd',
default: './'
})
console.log('list items!')
})
.example('$0 count', 'count the lines in the given file')
.help('h')
.alias('h', 'help')
.argv;
以下コマンドを実行してみます。countのみ確認してますが無事オプションは追加されたようです。
$ node app.mjs count --help
app.mjs count
Count the files in a directory
Options:
--version Show version number [boolean]
-h, --help Show help [boolean]
-d, --directory [default: "./"]
しかしながらコマンド実行後の挙動が何もないのは寂しいのでコードを変更して実際の挙動を確認していきます。addコマンドのtitleオプションを指定してコンソール上にタイトルを表示させます。
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})
},
function(argv){
console.log(`Title: ${argv.title}`)
}
)
.example('$0 add --title hoge', 'add title "hoge"')
.help('h')
.alias('h', 'help')
.argv;
以下コマンドを実行していきます。
$ node app.mjs add --help
app.mjs add
add note
Options:
--version Show version number [boolean]
-h, --help Show help [boolean]
-t, --title [required] [default: ""]
$ node app.mjs add --title hoge
Title: hoge
$ brew install node
$ brew install nvm
インストール完了後に以下を実施
$ mkdir ~/.nvm # nvmのワーキングディレクトリ
$ vim ~/.zshrc # nvmの環境変数を設定、以下の記述を構成ファイルに追加する
export NVM_DIR=”$HOME/.nvm”
[ -s “/opt/homebrew/opt/nvm/nvm.sh” ] && \. “/opt/homebrew/opt/nvm/nvm.sh” # This loads nvm
[ -s “/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm” ] && \. “/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm” # This loads nvm bash_completion
ただしNVM_DIR は任意の場所に設定できますが、/opt/homebrew/opt/nvm から変更しないままだと、アップグレード/再インストール時に nvm でインストールされた node はすべて壊れてしまう、という警告が出ています。これはどう対応したら良いのだろうか??#TODO
$ brew install npm
それぞれインストール完了後にコマンドライン上でnode/nvm/npmと叩いて正しく呼び出せるか確認すると良いでしょう。
適当なリポジトリを作っておいて公式ドキュメントをもとにコードを写経してみます。
コードを書き終わったら以下コマンドを実行してサーバーを走らせます。
$ node app.js
Server running at http://127.0.0.1:3000/
localhost:3000にアクセスするとHellor Worldが返されます。
先ほどのコードを以下コマンドで実行することでデバッグクライアントが待機するようです。
$ node –inspect app.js
Debugger listening on ws://127.0.0.1:9229/21ab3436-839a-405f-8081-dd3dce1cf83a
For help, see: https://nodejs.org/en/docs/inspector
Server running at http://127.0.0.1:3000/
コマンドのレスポンス1行目がインスペクタクライアントのURLになります。ChromiumベースのWebブラウザでchrome://inspect/#devicesと入力してインスペクタクライアントを開いてサーバーの挙動を確認すると良いかもしれません。
htmlを使わない環境下でも使える様々なAPIがあるようです。たとえば以下。
const fs = require('fs');
fs.writeFileSync('notes.txt', 'Hi there!')
ECMAScript形式だと以下のようになる
import * as fs from 'fs';
fs.writeFileSync('notes.txt', 'Hi there!')
ただし上記の形式の場合は以下のように拡張子に”m”をつけて実行する。
$ node app.mjs
まずはメインファイル
import { name } from './utils.mjs'
console.log(name);
次にutilsファイル
console.log('utils.mjs')
export const name = 'Mike';
以下コマンドを実行するとutils内の関数呼び出しとexportされた変数を参照できていることがわかる。
$ node app.mjs
util.js
Mike
さらに関数のexportも確認する。
console.log('util.js')
export const name = 'Mike';
export const add = function(a, b) {
return a + b;
};
import { name, add } from './utils.mjs'
console.log(name);
console.log(add(2, 1));
以下コマンドを実行すると関数addを呼び出せていることが確認できる。
$ app.mjs
util.js
Mike
3
小学3年生は
小学1年生は
「どうやったらライントレースできるのか?」を整理して教えようとしたがそれが良くなかった気がする。というのも1年生のmayuchikuwaさんは理屈抜きで「自分の考える最強の動き方」をまず自力で考えていた。その失敗を経て初めて理屈を教えた方が食いつきが良かったのでは?と思った。