Skip to content

module

https://www.yuque.com/qinsjs/jsinfo/ifmpz2

一个模块(module)就是一个 .js 文件

对于浏览器,必须使用 <script type="module"> 特性(attribute)来告诉浏览器,此脚本应该被当作模块(module)来对待。

Module 只通过 HTTP(s) 工作!!

一些核心知识

  1. 模块始终默认使用 use strict
  2. 顶级作用域(top-level scope)。即 变量只在本文件可见。
  3. 只有第一次导入被解析,后面无论 import 多少次,都是一样的。
  4. 模块中的 this 是 undefined

import.meta

import.meta 对象包含关于当前模块的信息。

export

js
export 任意声明
js
export function (){}

export class Anmin{}

函数 和 类 的声明后不需要使用分号!这是个大家都在用的规范。

导出与声明分开

即:

js
const a = 1;
const b = () => console.log("hello");

export { a, b };

import

js
// 此方式更好,建议使用这种方式
import { a, b } from "./xxx.js";

也可以导入为一个对象

js
import * as x3 from "./xxx.js";

console.log(x3.a);

as

import 和 export 都可以 as

js
import { sayHi as hi, sayBye as bye } from "./say.js";
js
export { sayHi as hi, sayBye as bye };

default

“一个模块只做一件事”

export

每个文件应该只有一个 export default

因为只有一个,所以可以没有名字:

js
// 没有类名
export default class { }

// 没有函数名
export default function( ) { }

export default 1;

export default ['Jan', 'Feb', 'Mar','Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

也可以主动 default:

js
function sayHi(user) {
  alert(`Hello, ${user}!`);
}

export { sayHi as default };

import

js
export default class User {}

export function sayHi(user) {}

这两种方式都是可以的

js
import { default as User, sayHi } from "./user.js";
js
import * as user from "./user.js";

let User = user.default; // 默认的导出

重新导出

export ... from ...

动态导入

加载模块并返回一个 promise。

import() 并不是函数,不要使用 call/apply!

script type="module",import() 也可以工作

示例:

js
export const config = {};

export default 1;
js
import("./config.js").then(console.log);
// {
//     config:(...),
//     default:(...),
//     Symbol(Symbol.toStringTag): "Module"
// }

浏览器特定功能

todo

“bare” module

严格来说,module 不支持裸模块(bare module)。必须是 URL(相对 或 绝对)

但是 Node.js 和 打包工具 有自己的路径处理方式,所以他们可以使用。

“nomodule”

js
<script type="module">
  // 现在浏览器会执行这里
</script>

<script nomodule>
   // 现在浏览器 知道 module 和 nomodule , 所以会跳过 nomodule
   // 老浏览器并不知道,所以老浏览器会执行这里。
   // 老浏览器也会 ignore module
</script>

Demo:静态 http 服务

pnpm add koa mime-types

文件放在 html 目录下

js
const path = require("path");
const fs = require("node:fs/promises");
const { createReadStream } = require("fs");

const Koa = require("koa");
const app = new Koa();
const mime = require("mime-types");

const l = console.log;

app.use(async (ctx) => {
  const dir = path.join(__dirname, "/html", path.dirname(ctx.path));
  let dirStat;

  try {
    dirStat = await fs.stat(dir);
  } catch (error) {}

  if (!dirStat?.isDirectory()) {
    l("无效路径 > ", dir);
    ctx.status = 404;
    ctx.body = "404 找不到对应的资源";
    return;
  }

  let fileStat;

  const name = path.basename(ctx.path);
  const ext = path.extname(ctx.path);

  const getFileName = function () {
    if (!name) return "index.html";

    if (ext) {
      return name;
    } else {
      return path.join(name, ".html");
    }
  };

  const fileName = getFileName();

  try {
    fileStat = await fs.stat(path.join(dir, fileName));
  } catch (error) {}

  if (!fileStat) {
    l("没有对应文件 > ", dir, name, ext);
    ctx.status = 404;
    ctx.body = "404 没有对应资源文件";
    return;
  }

  ctx.set("content-type", mime.lookup(fileName));
  ctx.body = createReadStream(path.join(dir, fileName), { encoding: "utf8" });
});

app.listen(3000);