使用多个 webpack 配置分别加载 Angular 2 及其依赖库

Load Angular 2 and its dependent libraries separately with multiple webpack configs

我目前有一个使用 webpack 2 构建的 angular 2 应用程序。我让它忽略任何 angular 或任何第三方库,因为我的意图是让那些 loaded/maintained 分别在不同的 webpack 捆绑过程中(与我的应用程序配置不同的 webpack 配置)。我想这样做,以便可以更新这些库,而无需在我的应用程序或任何其他使用这些库的应用程序上重新 运行 webpack。我目前使用 webpack DLL 进行此工作,但我仍然有一个问题,如果我更新该 webpack DLL,应用程序仍然需要使用新模块 ID 重新捆绑到 "re-sync" 本身。由于许多应用程序都指向这个 "core" 包,您可以想象这会很乏味。我不希望这些经常改变,但我希望有它的自由。

当我 运行 应用程序时出现错误,因为我的应用程序代码无法在 angular 库中找到诸如 "Output"、"Input"、.. 。ETC。有谁知道我如何可以包括 angular、rxjs、zone、core-js 等。在脚本标签、单独的 webpack 捆绑包或其他一些方式中,并让应用程序 webpack 捆绑包能够了解这些库并使用它们? lodash 之类的东西工作正常,因为它们作为全局变量加载,但是使用 angular 2 我无法以相同的方式工作。

我尝试创建一个 webpack "vendor" 包,其中仅包含 angular 2 库及其依赖项,例如 zone 和 rxjs。我在输出上设置了 library 属性,并尝试在应用程序 webpack 配置中使用 libraryTargetexternals 属性。仅使用应该在其中的特定代码就可以很好地创建捆绑包,但应用程序无法在此 "vendor" 捆绑包中找到任何模块。似乎应用程序代码中的导入语句无法在此 "vendor" 包中找到模块。

如果有人想查看我的 webpack 配置文件中的部分内容,请随时询问。

我设法解决了这个问题。对于任何想要做同样事情的人来说,这就是需要发生的事情。

您需要为 angular 库及其依赖项中的每个 umd 模块添加脚本标签,或者按照我的操作创建一个 gulp 任务以正确连接这些库订购并创建一个包含代码的供应商文件,并在脚本标签中引用该代码。

加载 umd 模块后,您可以告诉您的 webpack 配置忽略特定模块并使用 externals 配置将它们委托给全局变量 属性:

externals: [
    {
        'hammerjs': 'Hammer',
        'lodash': '_',

        'core-js/es6': 'core',
        'core-js/es7/reflect': 'core',

        'zone.js/dist/zone': 'Zone',

        '@angular/core': 'ng.core',            
        '@angular/compiler': 'ng.compiler',
        '@angular/common': 'ng.common',
        '@angular/platform-browser': 'ng.platformBrowser',
        '@angular/platform-browser-dynamic': 'ng.platformBrowserDynamic',            
        '@angular/http': 'ng.http',
        '@angular/router': 'ng.router',
        '@angular/forms': 'ng.forms',

        '@angular/flex-layout': 'ng.flexLayout',
        '@angular/material': 'ng.material'            
    },
    function(context, request, callback) {
        if (/^rxjs/.test(request)) {
            return callback(null, 'Rx');
        }

        callback();
    }
],

它的作用是告诉 webpack 每当它遇到这些导入之一时,使用全局变量来引用它。全局变量现在存在是因为我们使用 umd 文件并单独加载它们。那里的函数用于 rxjs 并在遇到以 "rxjs".

开头的导入语句时使用 Rx 全局变量

下面列出了 umd 文件,以防有人还不知道。这些文件可以在各种模块加载器中导入,也可以通过全局变量访问:

// Third party JavaScript libs
'./node_modules/hammerjs/hammer.min.js', // Required by @angular/material
'./node_modules/lodash/lodash.min.js',

// Polyfills (required by @angular/*)
'./node_modules/core-js/client/shim.min.js',
'./node_modules/zone.js/dist/zone.min.js',

// RxJS
'./node_modules/rxjs/bundles/Rx.min.js', // Required by @angular/*

// Angular Framework (order matters)
'./node_modules/@angular/core/bundles/core.umd.min.js',
'./node_modules/@angular/common/bundles/common.umd.min.js',
'./node_modules/@angular/compiler/bundles/compiler.umd.min.js', // Don't need this if using AoT...
'./node_modules/@angular/platform-browser/bundles/platform-browser.umd.min.js', // Used for AoT
'./node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.min.js', // Used for JiT
'./node_modules/@angular/http/bundles/http.umd.min.js',    
'./node_modules/@angular/forms/bundles/forms.umd.min.js',
'./node_modules/@angular/router/bundles/router.umd.min.js',

// Third party Angular libraries
'./node_modules/@angular/flex-layout/bundles/flex-layout.umd.js',
'./node_modules/@angular/material/bundles/material.umd.js'

此过程允许您更改 "vendor" javascript 捆绑包,而无需在每个依赖它的应用程序上 运行 webpack。当然,如果应用程序需要新功能,您需要在应用程序上使用 运行 webpack,但只要更新 angular 或任何其他外部库而不破坏更改,那么这会很好用。唯一的缺点是 tree shaking 现在不能用于供应商代码......但它仍然适用于使用 webpack 的应用程序。