【问题标题】:Why do i need to import modules everytime in webpack bundle?为什么我每次都需要在 webpack 包中导入模块?
【发布时间】:2018-04-25 08:53:20
【问题描述】:

我使用webpack生成一个bundle文件,即app.bundle.js。似乎是在每个单独的 js 文件中我需要导入它将使用的模块。

我一直在努力解决这个问题,但它让我难以捉摸。我理解捆绑过程的方式是简化:它将您指定的所有文件合并到一个大输出文件中。

这应该意味着一个类在那个大文件中被声明一次,这应该足以作为所有其他类的参考。为什么我需要一次又一次地导入它,而它应该只是在捆绑文件的顶部,可供此后编写的所有其他代码使用?

P.S(一个简单的例子)

我有以下文件:

A.js

class A {
    doIt(){
      console.log(this);
    }
}

B.js:

import {A} from "a.js";

class B extends A {

}

main.js:

import {A} from "a.js"
import {B} from "b.js"

要在 main.js 中使用 B,我还需要导入 A。如果 A 有另一个子类,我也需要导入它。对我来说,这看起来很疯狂,以至于我宁愿将所有东西都固定在窗口上。

如果有人知道,请帮助我了解我缺少什么。

【问题讨论】:

标签: javascript import webpack


【解决方案1】:
  1. Webpack 获取您指定的所有文件并将它们合并到一个大输出文件中,以便在正确的时间、正确的范围内拉入相关模块。

如果我们有:

// sum.js

var sum = function (a, b) { return a + b;};

// multiply.js

// slightly contrived here - we're going to repeatedly sum to multiply, to illustrate dependency
// interaction
var multiply = function (a, b) {
    var total = 0;
    for (var i = 0; i < b; i++) {
        total = sum(a, total);
    }
    return total;
};

// index.js

- our application logic
var totalMultiply = multiply(5, 3);
var totalSum = sum(5, 3);

console.log('Product of 5 and 3 = ' + totalMultiply);
console.log('Sum of 5 and 3 = ' + totalSum);

// index.html

- our entry point to our application
<html>
<head>
    <script src="src/sum.js"></script>
    <script src="src/multiply.js"></script>
    <script src="src/index.js"></script>
</head>
</html>

这样的输出将是:

Product of 5 and 3 = 15
index.js:17 Sum of 5 and 3 = 8
  • 如果我们在 index.html 中的顺序错误,我们的应用程序将无法运行。如果 index.js 包含在任何其他依赖项之前,或者 sum.js 包含在 multiply.js 之后,我们将得到错误。这就是捆绑文件的重点。
  • Webpack 可以将我们所有的依赖项拉到一个文件中bundle file,这意味着只需要下载一个依赖项。

2- 使依赖项可用并链接它们

  • CommonJS 使用 module.exports 将函数或变量导出或提供给其他代码。它使用 require 然后拉入这些导出的值。

// sum.js

var sum = function (a, b) {
    return a + b;
};
module.exports = sum;

//乘法.js

var sum = require('./sum');

var multiply = function (a, b) {
    var total = 0;
    for (var i = 0; i < b; i++) {
        total = sum(a, total);
    }
    return total;
};
module.exports = multiply;

// index.js

- our application logic
var multiply = require('./multiply');
var sum = require('./sum');

var totalMultiply = multiply(5, 3);
var totalSum = sum(5, 3);

console.log('Product of 5 and 3 = ' + totalMultiply);
console.log('Sum of 5 and 3 = ' + totalSum);
  • 请注意,我们已将 sum 和 multiply 提供给其他代码,并且我们已在 multiple.js 和 index.js 中引入了这些导出的函数。
  • 还要注意,我们的 index.html 现在只需要拉入一个文件 - bundle.js。
  • 我们可以公开我们想要的内容并使其他代码有效地保密

这就是重点,你需要告诉 webpack 你需要哪些模块来相互通信和共享数据。与 webpack 中一样,每个模块的表面积都比完整程序小,这使得验证、调试和测试变得微不足道。编写良好的模块提供了可靠的抽象和封装边界,因此每个模块在整个应用程序中都具有连贯的设计和明确的目的。

  • 我们还将网络调用从 3 个(sum.js、multiply.js 和 index.js)减少到 一次调用 - 这将有助于加快加载时间。

请注意,除非您确实需要它,否则我不建议将库或模块公开为全局,即模块系统的重点是显式声明依赖项。

  • ProvidePlugin:此插件使模块可作为每个模块中的变量使用。仅当您使用该变量时才需要该模块。

示例:在每个模块中都可以使用 $ 和 jQuery,而无需编写 require("jquery")。

new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
})

所以:

// app.js
$.ajax(...);

被有效地转译成:

// app.js
require('jquery').ajax(...);

webpack 将生成一个加载指定模块的代码,就像它为 import 或 require 所做的一样。

【讨论】:

  • 我理解捆绑背后的原因和想法。对我来说完全陌生的是必须两次导入“sum”。在我的场景中,我有一个类是另一个类的子类,依此类推。我可以直接向窗口添加东西,但感觉完全错误,我宁愿避免这样做。有没有办法使模块在全球范围内可用或类似于我所描述的东西?检查我发布的另一个相关问题:stackoverflow.com/questions/47247545/…
  • B) 另外,我不确定它有什么不同,但我没有使用 module.exports / require 系统。我使用从 Y 导入 X 和普通导出系统(因为人们声称这是将来会在规范中使用的系统)如果你有任何我想听听的 cmets
  • A) 我不建议将库或模块公开为全局,除非您确实需要它,即模块系统的重点是显式声明依赖关系。我会更新我的答案。
  • B) 1- CommonJS 模块的设计考虑了服务器开发。当然,API 是同步的。换句话说,模块是在源文件中按需要的顺序加载的。所以,我不建议在客户端使用它。 2- 导入和导出指令的静态特性允许静态分析器在不运行代码的情况下构建完整的依赖关系树。 ES2015 是正确的方法。它将始终受到支持,并且当前使用转译器和 polyfill 的支持非常好。参考:auth0.com/blog/javascript-module-systems-showdown
  • C) 注意:如果你让一个类全局可用,那么你将破坏模块化系统,因为它会产生很多错误和冲突。如果我们假设您在一年左右后再次开始编辑项目,并且错误地编写了全局可用类的相同名称。
猜你喜欢
  • 1970-01-01
  • 2020-12-28
  • 2020-05-20
  • 2019-12-31
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
相关资源
最近更新 更多