1. Module Methods (模块方法)

本节涵盖了在使用webpack编译代码中可用的所有方法。当使用webpack来打包应用程序时,您可以从各种模块语法风格中选择,包括ES6, CommonJS, 和 AMD.

[warning] 注:

虽然webpack支持多种模块语法,但我们建议使用单一语法来保持一致性,避免奇怪的行为/bug。这里有一个混合ES6和CommonJS的 例子,当然也有其他的例子。

1.1. ES6 (推荐)

webpack的版本2支持ES6模块语法,这意味着您可以使用importexport,而不需要像babel 这样的工具来处理这个问题。请记住,您仍然可能需要其他ES6+特性的babel。以下方法被webpack支持:

1.1.1. import

静态 import 其他模块的export

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

[warning] 注:

这里的关键字是静态。正常的import语句不能在其他逻辑中动态地使用,也不能包含变量。请参阅下面的规范,了解更多信息和import()动态用法。

1.1.2. export

导出任何作为default或者命名的导出

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

// 默认 export
export default {
  // Some data...
}

1.1.3. import()

import('path/to/module') -> Promise

动态加载模块。对import()的调用被视为分割点,这意味着被请求的模块和它的子节点(children)被分割成一个单独的chunk。

T> The ES2015 Loader spec defines import() as method to load ES2015 modules dynamically on runtime.

[info] 注:

ES2015 Loader 规范 定义了import()作为方法来在运行时动态加载 ES2015 模块

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

[warning] 注:

这个特性在内部依赖于Promise。如果你在老旧浏览器中使用import(),记住使用一个pliyfill来塞住(shim)Promise。例如使用es6-promise或者promise-polyfill

import规范不允许不允许对chunk的名称或其他属性进行控制,因为“chunk”只是webpack中的一个概念。幸运的是,webpack通过注释允许一些特殊的参数,这样就不会违反规范:

import(
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  'module'
);

webpackChunkName: 新chunk的名称。从webpack 2.6.0起,在给定的字符串中,占位符[index][request]分别被支持为一个递增的数字或实际已解析的文件名。

webpackMode: 从 webpack 2.6.0起,可以指定用于解析动态导入的不同模式。以下选项是支持的:

  • "lazy" (默认): 为每一个被import()的模块生成一个懒加载chunk
  • "lazy-once": 生成一个单一的懒加载chunk,可以满足import的所有调用。在第一次调用import()时将获取chunk,随后对import()的调用将使用相同的网络响应。请注意,这只在部分动态语句的情况下才有意义,例如import(`./locales/${language}.json`),其中有多个模块路径可能会被请求。
  • "eager": 不生成额外的chunk。所有的模块都包含在当前的块中,不需要额外的网络请求。Promise仍会被返回,但已得到解决。与静态导入不同的是,在调用import()之前,模块不会被执行。
  • "weak": 如果模块函数已经以其他方式加载,则尝试装入模块(例如,导入它的另一个chunk或包含加载了模块的脚本)。仍然会返回一个Promise,但是,只有当chunk已经在客户端上才能成功地解析。如果模块不可用,则Promise被拒绝。网络请求永远不会被执行。当需要的chunk总是在初始请求(嵌入在页面内)中手动提供时,这对于通用的渲染是很有用的,但是在应用程序导航将触发导入而不是初始请求的情况下,这是很有用的。

[info] 注:

这两个选项都可以像/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */那样组合在一起。它被解析为一个没有花括号({})的JSON5对象

-

[warning]注:

完全动态的语句将会失败,例如import(foo),因为webpack至少需要一些文件位置信息。这是因为foo可能是您的系统或项目中的任何文件的任何路径。import()必须至少包含关于模块所在位置的一些信息,因此bundling可以被限制为特定的目录或文件集。

-

[warning]注:

包含在import()调用中可能被请求的每个模块都包括在内。例如,import(`./locale/${language}.json`)将导致./locale目录中的每个.json文件被打包到到新chunk中。在运行时,当变量language被计算时,任何文件如english.jsongerman.json将可以用于打包。

-

[warning]注:

在webpack中使用System.import不符合推荐的规范,因此在webpack 2.1.0测试版中被弃用,转而支持import()

1.2. CommonJS

CommonJS的目标是在浏览器之外为JavaScript指定一个生态系统。下面的CommonJS方法是由webpack支持的:

1.2.1. require

require(dependency: String)

同步从另一个模块检索导出。编译器将确保依赖项在输出bundle中可用。

var $ = require("jquery");
var myModule = require("my-module");

[warning]注:

异步地使用它可能没有预期的效果。

1.2.2. require.resolve

require.resolve(dependency: String)

同步检索模块的ID。编译器将确保依赖项在输出bundle中可用。查看module.id以更多信息。

[warning]注:

模块ID是webpack中的一个数字(与NodeJS相比,它是一个字符串——文件名)。

1.2.3. require.cache

类型:数组

同一模块的多次require只会有一次模块执行和一次导出。因此在运行时存在一个缓存。从这个缓存中删除值会导致新的模块执行和新的导出。

[warning]注:

这种情况只需要在少数情况下进行兼容性!

var d1 = require("dependency");
require("dependency") === d1
delete require.cache[require.resolve("dependency")];
require("dependency") !== d1
// in file.js
require.cache[module.id] === module
require("./file.js") === module.exports
delete require.cache[module.id];
require.cache[module.id] === undefined
require("./file.js") !== module.exports // in theory; in praxis this causes a stack overflow
require.cache[module.id] !== module

1.2.4. require.ensure

W> require.ensure() is specific to webpack and s by import().

[warning]注:

require.ensure()是特定于webpack的,并被import()取代

require.ensure(dependencies: String[], callback: function(require), errorCallback: function(error), chunkName: String)

将给定的dependencies拆分为一个单独的bundle,该bundle将被异步加载。在使用CommonJS模块语法时,这是动态加载依赖项的唯一方法。也就是说,这段代码可以在执行上下文(execution中运行,只有在满足特定条件时才加载dependencies

W> This feature relies on Promise internally. If you use require.ensure with older browsers, remember to shim Promise using a polyfill such as es6-promise or promise-polyfill.

[warning]注:

这个特性在内部依赖于Promise。如果你在老旧浏览器中使用require.ensure,记得添加polyfill。如es6-promise或者promise-polyfill

var a = require('normal-dep');

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

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

以下参数按照上面指定的顺序来阐述:

  • dependencies: 字符串数组,声明要执行的callback中的代码所需要的所有模块。
  • callback: 回调函数,一旦加载了依赖项,webpack将会执行它。require函数的实现被作为参数发送给这个函数。函数体可以使用它来进一步require()它需要执行的模块。
  • errorCallback: 当webpack无法加载依赖项时执行的函数。
  • chunkName: 这个特定的require.ensure()所创建的chunk的名称。通过将相同的chunkName传递给各种require.ensure()调用,我们可以将它们的代码合并到一个单独的chunk中,只产生一个浏览器必须加载的bundle。

[warning]注:

尽管require的实现被作为一个参数传递给callback函数,在callback中可以使用一个任意的名称,不是由webpack的静态解析器处理的,例如equire.ensure([], function(request) { request('someModule'); })。所以请使用require代替,例如require.ensure([], function(require) { require('someModule'); })

1.3. AMD

异步模块定义(AMD)是一个JavaScript规范,它定义了一个用于编写和加载模块的接口。以下的AMD方法是被webpack支持的:

1.3.1. define (使用工厂函数)

define([name: String], [dependencies: String[]], factoryMethod: function(...))

如果提供了dependencies,那么将使用每个依赖项的导出(按照相同的顺序)调用factoryMethod。如果不提供dependencies,则会使用requireexportsmodule(为了兼容性!)调用factoryMethod。如果该函数返回一个值,则该值将由模块导出。编译器确保每个依赖项都可用

[warning]注:

webpack忽略了name参数。

define(['jquery', 'my-module'], function($, myModule) {
  // Do something with $ and myModule...

  // Export a function
  return function doSomething() {
    // ...
  };
});

[warning]注:

不能在异步函数中使用。

1.3.2. define (使用 value)

define(value: !Function)

这将简单地导出所提供的value。这里的value可以是任何东西,只要不是一个函数。

define({
  answer: 42
});

[warning]

不能在异步函数中使用。

1.3.3. require (amd-version)

require(dependencies: String[], [callback: function(...)])

类似于require.ensure,这将把给定的dependencies划分为一个单独的bundle,它将被异步加载。callback将在dependencies数组中对每个依赖项的导出进行调用。

[warning] 注:

这个特性在内部依赖于Promise。如果你在老旧浏览器(例如 Internet Explorer 11)中使用AMD,记得添加polyfill。如es6-promise或者promise-polyfill

require(['b'], function(b) {
  var c = require("c");
});

[warning] 注:

没有提供指定chunk名称的选项。

1.4. Labeled Modules

内部的LabeledModulesPlugin使您可以使用以下方法来导出和请求您的模块:

1.4.1. export 标签

导出给定的value。这个标签可以在函数声明或变量声明之前出现。函数名或变量名是输出值的标识符。

export: var answer = 42;
export: function method(value) {
  // Do something...
};

W> Using it in an async function may not have the expected effect.

[warning] 注:

在异步函数中使用它可能没有预期的效果。

1.4.2. require 标签

使当前范围内的依赖项中所有导出可用。require标签可以出现在字符串之前。依赖项必须导出带有export标签的值。不能使用CommonJS或AMD模块。

some-dependency.js

export: var answer = 42;
export: function method(value) {
  // Do something...
};
require: 'some-dependency';// 依赖文件名称
console.log(answer);
method(...);

1.5. Webpack

除了上面提到的模块语法之外,webpack还允许一些自定义的、webpack特有的方法:

1.5.1. require.context

require.context(directory:String, includeSubdirs:Boolean /* 可选, 默认值 true */, filter:RegExp /* 可选 */)

使用directory的路径指定一组依赖项,一个includeSubdirs选项,以及一个对包含的模块进行更细粒度控制的filter(过滤器)。之后,这些问题就可以轻松解决了:

var context = require.context('components', true, /\.html$/);
var componentA = context.resolve('componentA');

1.5.2. require.include

require.include(dependency: String)

包含一个dependency而不执行它。这可以用于在输出chunk中优化模块的位置。

require.include('a');
require.ensure(['a', 'b'], function(require) { /* ... */ });
require.ensure(['a', 'c'], function(require) { /* ... */ });

这将导致以下输出:

  • entry chunk: file.js and a
  • 匿名(anonymous)chunk: b
  • 匿名(anonymous)chunk: c

如果没有require.include('a'),它将被复制进匿名chunk中。

1.5.3. require.resolveWeak

类似于require.resolve,但这不会将module拉入bundle中。这就是所谓的“弱(weak)”依赖性。

if(__webpack_modules__[require.resolveWeak('module')]) {
  // 当模块可用时做一些事情...
}
if(require.cache[require.resolveWeak('module')]) {
  // 在模块加载之前做一些事情...
}

// 你可以执行动态 resolves ("context"),就像其他的require/import方法一样。
const page = 'Foo';
__webpack_modules__[require.resolveWeak(`./page/${page}`)]

[info] 注:

require.resolveWeak是通用渲染(SSR + 代码分割)的基础(SSR+代码分裂),就像在诸如react-通用组件这样的包中使用。它允许代码在客户机上同步地渲染服务器和初始页面加载。它要求chunk是被手动提供,或者是某种可用的。它能够请求(require)模块,而不需要指出它们应该被打包到一个chunk中。它与import()结合使用,当用户导航触发其他导入时,它将接管该操作。

Copyright © tuzhu008 2017 all right reserved,powered by Gitbook该文件修订时间: 2017-11-21 10:09:33

results matching ""

    No results matching ""