CC 4.0 许可证

本节内容来自以下链接的内容,并受 CC BY 4.0 许可证约束。

除非另有说明,以下内容可以被认为是基于原始内容的修改和删除的结果。

模块方法

本节介绍了使用 Rspack 编译的代码中可用的所有方法。当使用 Rspack 打包您的应用程序时,您可以从多种模块语法样式中进行选择,包括 ES6、CommonJS。

虽然 Rspack 支持多种模块语法,但我们建议您遵循单一语法以保持一致性并避免出现奇怪的行为/错误。

实际上,Rspack 会对 .mjs 文件、.cjs 文件或 .js 文件执行推荐,当它们最近的父 package.json 文件包含一个值为 "module""commonjs""type" 字段时。在您继续阅读之前,请注意这些强制措施。

  • .mjs.js,在 package.json 中使用 "type": "module"
    • 不允许使用 CommonJS,例如,您不能使用 requiremodule.exportsexports
    • 导入时需要文件扩展名,例如,您应该使用 import './src/App.mjs' 而不是 import './src/App'(您可以使用 Rule.resolve.fullySpecified 禁用此强制措施)
  • .cjs.js,在 package.json 中使用 "type": "commonjs"
    • import 和 export 都不可用

Rspack 原生支持 ES6 模块语法,您可以使用静态 importexportimport() 语法。

警告

请记住,您可能仍然需要 SWC 或 Babel 来处理其他 ES6+ 功能。

import

静态 import 另一个模块的 export

import MyModule from './my-module.js';
import { NamedExport } from './other-module.js';

您也可以 import 数据 URI

import 'data:text/javascript;charset=utf-8;base64,Y29uc29sZS5sb2coJ2lubGluZSAxJyk7';
import {
  number,
  fn,
} from 'data:text/javascript;charset=utf-8;base64,ZXhwb3J0IGNvbnN0IG51bWJlciA9IDQyOwpleHBvcnQgY29uc3QgZm4gPSAoKSA9PiAiSGVsbG8gd29ybGQiOw==';

export

导出任何内容作为 default 或命名导出。

// Named exports
export var Count = 5;
export function Multiply(a, b) {
  return a * b;
}

// Default export
export default {
  // Some data...
};

动态 import()

function import(path: string): Promise;

动态加载模块。对 import() 的调用被视为拆分点,这意味着请求的模块及其子模块将被拆分到单独的块中。

if (module.hot) {
  import('lodash').then(_ => {
    // Do something with lodash (a.k.a '_')...
  });
}
警告

此功能在内部依赖于 Promise。如果您在旧版浏览器中使用 import(),请记住使用 polyfill(例如 es6-promisepromise-polyfill)来对 Promise 进行垫片。

import() 中的动态表达式

无法使用完全动态的导入语句,例如 import(foo)。因为 foo 可能是系统或项目中任何文件的任何路径。

import() 必须包含至少一些有关模块所在位置的信息。打包可以限制到特定目录或一组文件,以便在您使用动态表达式时,import() 调用中可能请求的每个模块都包含在内。例如,import(./locale/${language}.json) 将导致 ./locale 目录中的每个 .json 文件都被打包到新块中。在运行时,当变量 language 已计算完毕时,任何类似于 english.jsongerman.json 的文件都将可供使用。

// imagine we had a method to get language from cookies or other storage
const language = detectVisitorLanguage();
import(`./locale/${language}.json`).then(module => {
  // do something with the translations
});

魔术注释

Rspack/Webpack 特定

内联注释使功能正常工作。通过向导入添加注释,我们可以做一些事情,例如命名我们的块或选择不同的模式。有关这些魔术注释的完整列表,请参见下面的代码,然后解释这些注释的作用。

// Single target
import(
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  /* webpackExports: ["default", "named"] */
  /* webpackFetchPriority: "high" */
  'module'
);

// Multiple possible targets
import(
  /* webpackInclude: /\.json$/ */
  /* webpackExclude: /\.noimport\.json$/ */
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  /* webpackPrefetch: true */
  /* webpackPreload: true */
  `./locale/${language}`
);
webpackIgnore
  • 类型: boolean

当设置为 true 时,禁用动态导入解析。

警告

请注意,将 webpackIgnore 设置为 true 会选择退出代码拆分。

webpackMode
  • 类型: "eager" | "lazy" | "weak" | "lazy-once"

可以指定用于解析动态导入的不同模式。支持以下选项

  • 'lazy' (默认):为每个 import() 的模块生成一个延迟加载的块。
  • 'lazy-once':生成一个单一的延迟加载的块,可以满足对 import() 的所有调用。该块将在第一次调用 import() 时获取,后续对 import() 的调用将使用相同的网络响应。请注意,这仅在部分动态语句的情况下有意义,例如 import("./locales/${language}.json"),其中可能请求多个模块路径。
  • 'eager':不生成额外的块。所有模块都包含在当前块中,并且不会发出额外的网络请求。仍然会返回一个 Promise,但它已经解析。与静态导入相比,模块直到调用 import() 时才会执行。
  • 'weak':如果模块函数已以某种其他方式加载(例如,另一个块导入了它或包含该模块的脚本已加载),则尝试加载该模块。仍然会返回一个 Promise,但仅在块已在客户端上的情况下才会成功解析。如果模块不可用,则 Promise 会被拒绝。永远不会执行网络请求。这在通用渲染中非常有用,因为必需的块始终在初始请求中手动提供(嵌入在页面中),但在应用程序导航将触发未在初始请求中提供的导入的情况下则不适用。
webpackPrefetch
  • 类型
    • number:块预取优先级
    • booleanfalse 表示不预取,true 表示优先级为 0

告诉浏览器该资源可能在将来的某些导航中需要,有关更多详细信息,请参见 预取/预加载模块

webpackPreload
  • 类型
    • number:块预加载优先级
    • booleanfalse 表示不预加载,true 表示优先级为 0

告诉浏览器该资源可能在当前导航期间需要,有关更多详细信息,请参见 预取/预加载模块

webpackChunkName
  • 类型:: string

新块的名称。

webpackFetchPriority
  • 类型:: "low" | "high" | "auto"

设置 fetchPriority 用于特定的动态导入。也可以使用 module.parser.javascript.dynamicImportFetchPriority 选项为所有动态导入设置全局默认值。

webpackInclude
  • 类型:: Regexp

一个正则表达式,将在导入解析期间与之匹配。只有与之匹配的模块才会被捆绑。

webpackExclude
  • 类型:: Regexp

一个正则表达式,将在导入解析期间与之匹配。任何与之匹配的模块都不会被捆绑。

信息

请注意,webpackIncludewebpackExclude 选项不会干扰前缀。例如:./locale

webpackExports
  • 类型:: string | string[]

告诉 webpack 只打包动态 import() 模块中指定的导出内容。这可以减小块的输出大小。

CommonJS

Rspack 也原生支持 CommonJS 语法,您可以使用 requiremodule.exports 方法。

require

同步获取来自另一个模块的导出内容。

require(dependency: string);

require.resolve

同步获取模块的 ID。建议将其视为不透明值,只能与 require.cache[id]__webpack_require__(id) 一起使用(最好避免这种用法)。

require.resolve(dependency: string);
警告

模块 ID 的类型可以是数字或字符串,具体取决于 optimization.moduleIds 配置。

require.cache

对同一模块的多次 require 操作只会执行一次模块,并且只会导出一次。因此,运行时存在一个缓存。从该缓存中删除值会导致执行新模块并导出新的内容。

var d1 = require('dependency');
require('dependency') === d1;
delete require.cache[require.resolve('dependency')];
require('dependency') !== d1;

require.context

Rspack/Webpack 特定

require.context 是 webpack 特有的一个函数,允许您动态地 require 一组模块。

您可以在代码中使用 require.context,Rspack 会在构建过程中解析并引用匹配的模块。

提示

require.context 的返回值与 import.meta.webpackContext 相同。建议使用 import.meta.webpackContext,它更强大。

  • 类型
function requireContext(
  /**
   * A directory to search.
   */
  directory: string,
  /**
   * Whether subdirectories should be searched.
   * @default true
   */
  includeSubdirs?: boolean,
  /**
   * A regular expression to match files.
   * @default /^\.\/.*$/ (any file)
   */
  filter?: RegExp,
  /**
   * Module loading mode.
   * @default 'sync'
   */
  mode?: 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy-once',
): Context;
  • 示例
// Create a context, with files from the test directory that
// can be required with a request ending with `.test.js`.
const context = require.context('./test', false, /\.test\.js$/);
// Create a context with all files in the parent folder and
// descending folders ending with `.stories.js`.
const context = require.context('../', true, /\.stories\.js$/);
// If mode is set to 'lazy', the underlying modules will be loaded asynchronously
const context = require.context('./locales', true, /\.json$/, 'lazy');
提示

Rspack 使用静态分析在编译过程中解析 require.context 的参数。因此,参数必须是 字面量

例如,filter 的值不能是变量,也不能是 new RegExp() 生成的值。它只能是正则表达式字面量。

require.ensure

Rspack/Webpack 特定
提示

require.ensure() 是 rspack/webpack 特有的,已被 import() 取代。

将给定的 dependencies 分割到一个单独的包中,该包将被异步加载。当使用 CommonJS 模块语法时,这是动态加载 dependencies 的唯一方法。这意味着,此代码可以在执行期间运行,只有在满足特定条件时才会加载依赖项。

警告

此功能依赖于 Promise。如果您在较旧的浏览器中使用 require.ensure,请记住使用 polyfill(如 es6-promisepromise-polyfill)来 shim Promise。

  • 类型
function requireEnsure(
  /**
   * An array of strings declaring all modules required for the code in the callback to execute.
   */
  dependencies: String[],
  /**
   * A function that webpack will execute once the dependencies are loaded.
   * An implementation of the require function is sent as a parameter to this function.
   * The function body can use this to further require() modules it needs for execution
   */
  callback: function(require),
  /**
   * A function that is executed when webpack fails to load the dependencies.
   */
  errorCallback?: function(error),
  /**
   * A name given to the chunk created by this particular require.ensure().
   * By passing the same chunkName to various require.ensure() calls,
   * we can combine their code into a single chunk, resulting in only one bundle that the browser must load.
   */
  chunkName?: String
): Context;
  • 示例
var a = require('normal-dep');

if (module.hot) {
  require.ensure(['b'], function (require) {
    var c = require('c');

    // Do something special...
  });
}

数据 URI 模块

Rspack 支持使用 importrequire 语法导入数据 URI 模块。

import

import DataURI from 'data:text/javascript,export default 42';

require

require('data:text/javascript,module.exports = 42');

此外,还支持 Base64 编码的请求

const {
  number,
  fn,
} = require('data:text/javascript;charset=utf-8;base64,ZXhwb3J0IGNvbnN0IG51bWJlciA9IDQyOwpleHBvcnQgZnVuY3Rpb24gZm4oKSB7CiAgcmV0dXJuICJIZWxsbyB3b3JsZCI7Cn0=');
提示

数据 URI 模块可以用作实现虚拟模块的一种方法,例如与 Loader 结合以在运行时动态加载自定义模块。