ES2020 でimport.meta
がリリースされた。
この機能を使うと、モジュールのメタ情報を取得することができる。
例えば、当該モジュールのパスを取得することができる。
モジュールのメタ情報を取得する機能であるため、CommonJS や Script モードで使用するとエラーになる。
import.meta
でどのような情報を取得できるか、Node.js、Deno、ブラウザで試してみた。
それぞれのバージョンは以下の通り。
- Node.js:
14.7.0
- Deno:
1.2.2
- Google Chrome:
84.0.4147.105
Node.js
前述の通り CommonJS だとエラーになるため、ES Modules で使う必要がある。
// SyntaxError: Cannot use 'import.meta' outside a module console.log(import.meta);
Node.js で ES Modules を使う方法については、以下の記事に書いた。
ES Modules として書かれたファイルなら、import.meta
を使える。
// [Object: null prototype] { // url: 'file:///Users/numb/index.mjs' // } console.log(import.meta);
ES Modules では__dirname
や__filename
を使えないが、import.meta.url
でファイルパスを取得することができる。
// console.log(__dirname); // ReferenceError: __dirname is not defined // console.log(__filename); // ReferenceError: __filename is not defined console.log(import.meta.url); // file:///Users/numb/index.mjs
Deno
Deno では、url
の他にmain
という名前の値を取得することができる。
console.log(import.meta); // { url: "file:///Users/numb/index.ts", main: true }
main
は、プログラムの起点として Deno に渡されたモジュールかどうかを、真偽値で持っている。
例えば、以下のモジュールがあったとする。
// meta-sub.ts console.log(import.meta.main); export const x = 1;
// meta.ts import { x } from "./meta-sub.ts"; console.log(x); console.log(import.meta.main);
この状況でmeta.ts
を実行すると、meta.ts
がメインのスクリプトとなるため(meta-sub.ts
はmeta.ts
に呼ばれているだけ)、meta-sub.ts
のimport.meta.main
はfalse
になる。
$ deno run meta.ts false 1 true
meta-sub.ts
を実行すれば、meta-sub.ts
のimport.meta.main
はtrue
になる。
$ deno run meta-sub.ts true
ブラウザ
以下のコードを Deno で実行して、サーバを立てる。
import { listenAndServe, } from "https://deno.land/std@0.63.0/http/mod.ts"; listenAndServe( { port: 8080 }, async (req) => { if (req.method !== "GET") { req.respond({ status: 405, }); return; } switch (req.url) { case "/": req.respond({ status: 200, headers: new Headers({ "content-type": "text/html", }), body: await Deno.readFile("./index.html"), }); break; case "/module.js": req.respond({ status: 200, headers: new Headers({ "content-type": "text/javascript", }), body: await Deno.readFile("./module.js"), }); break; default: req.respond({ status: 404, headers: new Headers({ "content-type": "text/plain", }), body: "Not found\n", }); break; } }, ); console.log("Server running on localhost:8080");
index.html
とmodule.js
はそれぞれ、以下の内容。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ImportMeta</title> </head> <body> <script type="module" src="/module.js"></script> </body> </html>
console.log(Object.keys(import.meta)); console.log(import.meta.url);
この状態でhttp://localhost:8080/
にアクセスするとindex.html
が表示され、そのなかでmodule.js
を読み込む。
script
タグにはtype="module"
をつけているが、これがないと Script モードになってしまい、import.meta
を使ったときにエラーになるので注意。
ブラウザのログには以下のように表示されており、import.meta.url
で当該ファイル(今回の場合はmodule.js
)の URL を取得できることが分かる。
["url"] http://localhost:8080/module.js