SystemJS 和 Webpack 有什么区别?

IT技术 javascript angular webpack node-modules systemjs
2021-03-18 10:45:02

我正在创建我的第一个 Angular 应用程序,我会弄清楚module加载器的作用是什么。为什么我们需要它们?我试图在谷歌上搜索和搜索,但我不明白为什么我们需要安装其中之一来运行我们的应用程序?

仅用于import从节点module加载内容难道就足够了吗?

我遵循了本教程(使用 SystemJS),它使我能够使用systemjs.config.js文件:

/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function(global) {
  // map tells the System loader where to look for things
  var map = {
    'app':                        'transpiled', // 'dist',
    '@angular':                   'node_modules/@angular',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    'rxjs':                       'node_modules/rxjs'
  };
  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
  };
  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'forms',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  // Individual files (~300 requests):
  function packIndex(pkgName) {
    packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
  }
  // Bundled (~40 requests):
  function packUmd(pkgName) {
    packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  }
  // Most environments should use UMD; some (Karma) need the individual index files
  var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
  // Add package entries for angular packages
  ngPackageNames.forEach(setPackageConfig);
  var config = {
    map: map,
    packages: packages
  };
  System.config(config);
})(this);

为什么我们需要这个配置文件?
为什么我们需要 SystemJS(或 WebPack 或其他)?
最后,在您看来,什么更好?

3个回答

SystemJS 在客户端工作。它在需要时按需动态加载module(文件)。您不必预先加载整个应用程序。例如,您可以在按钮单击处理程序中加载文件。

系统JS代码:

// example import at top of file
import myModule from 'my-module'
myModule.doSomething()

// example dynamic import (could be placed anywhere in your code)
// module not loaded until code is hit
System.import('my-module').then((myModule) {
  // myModule is available here
  myModule.doSomething()
});

除了配置它工作之外,这就是 SystemJS 的全部内容!您现在是 SystemJS 专家!

Webpack 是完全不同的,需要永远掌握。它与 SystemJS 做的事情不同,但是当使用 Webpack 时,SystemJS 变得多余。

Webpack 准备了一个名为 bundle.js 的文件 - 该文件包含所有 HTML、CSS、JS 等。因为所有文件都捆绑在一个文件中,所以现在不需要像 SystemJS 这样的惰性加载器(其中单个文件被加载为需要)。

SystemJS 的优点是延迟加载。该应用程序应该加载得更快,因为您不是一次性加载所有内容。

Webpack 的优点是,虽然应用程序最初加载可能需要几秒钟,但一旦加载和缓存,它就会闪电般快速。

我更喜欢 SystemJS,但 Webpack 似乎更时髦。

Angular2 快速入门使用 SystemJS。

Angular CLI 使用 Webpack。

Webpack 2(将提供摇树功能)处于测试阶段,所以现在迁移到 Webpack 可能是个糟糕的时机。

注意 SystemJS 正在实现ES6 module加载标准Webpack 只是另一个 npm module。

Task runners(对于那些想要了解 SystemJS 可能存在的生态系统的人的可选阅读)

对于 SystemJS,它的唯一职责是延迟加载文件,因此仍然需要一些东西来缩小这些文件、转换这些文件(例如从 SASS 到 CSS)等。这些必须完成的工作称为任务

配置后,Webpack 会正确地为您执行此操作(并将输出捆绑在一起)。如果你想用 SystemJS 做一些类似的事情,你通常会使用 JavaScript 任务运行器。最受欢迎的任务运行器是另一个名为gulp 的npm module

因此,例如,SystemJS 可能会延迟加载已被 gulp 缩小的缩小的 JavaScript 文件。Gulp 设置正确后,可以即时缩小文件并实时重新加载。实时重新加载是自动检测代码更改和自动浏览器刷新以进行更新。在开发过程中很棒。使用 CSS,实时流式传输成为可能(即,您可以看到页面更新了新样式,甚至无需重新加载页面)。

Webpack 和 gulp 还可以执行许多其他任务,这里就不一一介绍了。我提供了一个例子:)

我也是,我发现 SystemJS 和 JSPM 比 webpack 更容易使用。我还发现生产包更小(与另一个 webpack 示例项目相比)。这是我关于该主题的帖子:stackoverflow.com/questions/40256204/...
2021-05-02 10:45:02
您可以使用 Webpack 和延迟加载使用angular2-router-loader. 查看更多medium.com/@daviddentoom/...
2021-05-07 10:45:02
“Webpack 完全不同,需要永远掌握。它与 SystemJS 做的事情不同,但是,当使用 Webpack 时,SystemJS 变得多余。” 我得不同意。SystemJS 仍然允许开发人员进行开发,而不必为每次更改不断构建。我可以对 TS 文件进行更改、保存(它将自动调用 tsc.exe 并构建它),然后重新加载我的页面并且没有任何问题。使用 Webpack,我必须重新构建,这可能需要更长的时间,因为它会重新编译和构建所有内容我一直无法找到任何方法来避免使用 Webpack。
2021-05-08 10:45:02
你错了 Webpack!它允许您将捆绑与延迟加载相结合。此外,它透明地将延迟module捆绑成块。
2021-05-14 10:45:02
@AlexKlaus 谢谢你的例子!我正在寻找类似的东西:)
2021-05-16 10:45:02

如果您转到 SystemJS Github 页面,您将看到该工具的描述:

通用动态module加载器 - 在浏览器和 NodeJS 中加载 ES6 module、AMD、CommonJS 和全局脚本。

因为你在 TypeScript 或 ES6 中使用module,所以你需要一个module加载器。在 SystemJS 的情况下,systemjs.config.js允许我们配置module名称与其对应文件匹配的方式。

如果您明确使用它来导入应用程序的主module,则此配置文件(和 SystemJS)是必需的:

<script>
  System.import('app').catch(function(err){ console.error(err); });
</script>

使用 TypeScript 并将编译器配置到commonjsmodule时,编译器会创建不再基于 SystemJS 的代码。在此示例中,typescript编译器配置文件将如下所示:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs", // <------
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  }
}

Webpack 是一个灵活的module打包器。这意味着它更进一步,不仅处理module,还提供了一种打包应用程序的方法(concat 文件、uglify 文件……)。它还提供了一个开发服务器,用于开发负载重新加载。

SystemJS 和 Webpack 是不同的,但是使用 SystemJS,您仍然有工作要做(例如使用GulpSystemJS 构建器)来打包您的 Angular2 应用程序以进行生产。

事实上,对于生产来说,为module加载大量文件(单个文件(~300 个请求)或捆绑(~40 个请求))效率不高。您需要将所有内容收集到一两个(您的代码和第三方库代码)中,离线编译您的模板 (ngc) 并利用摇树来最小化包的重量。这篇文章可能会感兴趣:blog.mgechev.com/2016/06/26/...您还需要丑化 CSS 文件。
2021-04-24 10:45:02
@JonasKello 角度 cli 就是这种情况。请参阅此链接:github.com/angular/angular-cli在一节“的WebPack更新”?
2021-04-25 10:45:02
使用 npm start,您“只需”启动一个服务器,该服务器将根据您的 SystemJS module配置为您的应用程序提供服务...
2021-05-03 10:45:02
当您说“使用 SystemJS,您仍然有工作要做(例如使用 Gulp 或 SystemJS 构建器)来打包您的 Angular2 应用程序以进行生产”是我目前得到的npm start
2021-05-10 10:45:02
Google 已经正式迁移到 webpack。所以我想最好坚持使用社区的大多数人会使用的东西。我很快将我的 systemJS 项目迁移到 webpack。不完全确定如何做到这一点。
2021-05-10 10:45:02

到目前为止,我一直在使用 systemjs。它正在逐个加载文件,第一次加载需要 3-4 秒而没有缩小文件。切换到 webpack 后,我得到了很大的性能提升。现在只需要加载一个包文件(还有几乎从未改变并且几乎总是缓存的 polyfills 和供应商库),就是这样。现在只需一秒钟即可加载客户端应用程序。没有额外的客户端逻辑。加载的单个文件数量越少,性能越高。使用 systemjs 时,您应该考虑动态导入module以节省性能。使用 webpack,你主要关注你的逻辑,因为一旦包被缩小并缓存在你的浏览器中,性能仍然会很好。

您只回答了 OP 的一个问题,最好发表评论。
2021-05-01 10:45:02