【问题标题】:How do I include npm modules in webpack DLLs?如何在 webpack DLL 中包含 npm 模块?
【发布时间】:2016-10-09 07:40:21
【问题描述】:

我正在尝试使用 webpack 的 DLL 插件(1.13 版)创建一个 DLL 包,其中包含我的各种 React 项目所需的所有 npm 模块(即 preact、preact-compat、redux、react-redux、 redux-saga,重构)。我想通过我商店的内部 npm 存储库分发包含所有这些 npm 模块的 DLL 包。一些 Web 应用程序应该从 npm 存储库加载 DLL 包并使用其中包含的模块。

using DLLs in webpack from the webpack repo on GitHub 的示例中,名为 module 的模块包含在 alpha-DLL 中。 module 来自示例目录中的node_modules 目录(dll 目录下的一个目录)。

这可行,当我使用 node build.js 在 dll-user 目录中构建示例并查看 dll-user/js/output.js 时,我可以看到这些行:

/*!*****************************************************************************************!*\ !*** delegated ../node_modules/module.js from dll-reference alpha_e0d5512587ca63cbbd71 ***! \*****************************************************************************************/

名为module 的模块实际上并不是一个真正的npm 模块,它只是一个名为module.js 的文件,它直接位于node_module 目录中。我尝试包含一个“真实世界”的 npm 模块,在本例中为 preact

构建dlldll-user 项目后,查看output.js 文件,我可以看到preact 模块的整个代码都包含在输出中,没有发生委托。

如何才能使其正常工作?它是 webpack 中的错误吗?

我在 GitHub 上基于显示问题的 webpack DLL 示例创建了一个代码示例:https://github.com/pahund/webpack-dll-problem

【问题讨论】:

    标签: webpack


    【解决方案1】:

    编辑

    最初我只是让给定的示例工作,但不知道应该如何使用所有内容。我写了这个(块下的新内容):


    好的,所以我想我至少得到了一部分。 我会告诉你你必须做什么才能让你的例子发挥作用。

    有两种方法可以让它工作:

    1. 包含文件夹(即顶级)的package.json(和node_modules,如有必要)中删除preact。现在,preact 仅在 dll 文件夹中。
      然后在dll-user 内更改example.js 中的require 调用 文件夹到
      require("../dll/node_modules/preact")
      这应该可行,但不是我们想要的。

    2. 现在反过来了。从 dll 文件夹中删除 preact,但仅将其安装到 包含 文件夹。
      运行这两个构建脚本,并查看output.js 中的所有内容都已委托,包括preact


    新功能:

    好的,所以我在此处认为进行了更多探索。 (因为我们彼此认识并且可以一起工作,所以可以少说一些话,但我认为如果我对细节更明确一点,这也可能对其他人有所帮助,所以请耐心等待。)

    初步说明:我假设您想创建一个 dll 文件,您 1) 可以使用 npm 将其安装到项目中,并且 2) 以某种方式将单独的脚本标记包含到您的 HTML 中。该脚本在执行时创建一个全局变量,该变量公开一个函数,而您的应用程序脚本又使用该函数来解决依赖关系。 此外,我假设您已经为 dll 包设置了一个目录,其中仅安装了 package.json 和 webpack。

    首先你像这样创建一个webpack.config.js

    var webpack = require("webpack");
    var path = require("path");
    
    module.exports= {
      entry: ["preact"], // put here every module that goes into the dll
      output: {
        path: __dirname,
        filename: "index.js",
        library: "[name]_[hash]"
      },
      plugins: [
        new webpack.DllPlugin({
          path: path.join(__dirname, "[name]-manifest.json"),
          name: "[name]_[hash]" // (keep consistent with output.library)
        })
      ]
    };
    

    现在使用

    创建捆绑包及其清单
    $ webpack
    

    现在dll项目文件夹的结构是:

    dll-project
    |_ node_modules
    | |_ preact
    |_ main.js
    |_ main-mainifest.json
    |_ package.json
    |_ webpack.config.js
    

    现在您已将此包安装到另一个项目中,即您的应用中:

    app
    |_ node_modules
    | |_ dll-project
    |_ index.js
    |_ package.json
    |_ webpack.config.js
    

    这个 webpack.config.js 看起来像(或类似)这个:

    var webpack = require("webpack");
    
    module.exports= {
      entry: "./index.js",
      output: {
        path: __dirname,
        filename: "app.js"
      },
      plugins: [
        new webpack.DllReferencePlugin({
          scope: mydll,
          manifest: require("./node_modules/dll-project/main-manifest.json")
        })
      ]
    };
    

    在您的index.js 即您的应用程序代码中,您需要以这种方式位于 dll 包中的模块:

    var React = require("mydll/node_modules/preact/dist/preact");
    

    如果您运行webpack -d,您将在生成的app.js 中看到类似以下内容:

    /* 1 */
    /*!***************************************************************************************************!*\
      !*** delegated ./node_modules/preact/dist/preact.js from dll-reference main_2057857de340fdcfd8aa ***!
      \***************************************************************************************************/
    

    有人可能会问“为什么我不能只使用像require("preact") 这样的标准要求?”。答案是:可以,但是。但在这种情况下,您必须将所有这些依赖项安装在您的应用程序中的 dll 包中。因为在这种情况下,您将使用“映射模式”而不是“作用域模式”(请参阅​​Webpack Docs)。

    在作用域模式下,您必须明确require 相对于清单的模块路径。好处是:您不必在应用中安装该模块(并将其作为 package.json 中的依赖项)。

    在映射模式下,您可以像往常一样需要模块(就好像它已安装在应用程序的 node_modules 中一样),但您还必须使用 app.dll 将其安装在 dll 中。这是因为 Webpack 将首先评估 require 调用,然后意识到同一个模块也在 dll 包中,因此仅将别名(“委托...”)呈现到输出中。


    现在我认为这两种模式都有用例。如果您只构建应用程序本地 dll 以加快构建速度,则映射模式很酷。在这种情况下,您无论如何都要在本地安装并保存所有进入 dll 的 deps。但是,如果您想将 dll 包构建为可安装模块并在应用程序之间共享它——并且您不想在每个应用程序中跟踪 dll 中的所有模块——您很可能希望使用 scoped模式为更冗长的require 调用付出了代价。

    【讨论】:

    • 谢谢,我会检查您的解决方案并回复您。有趣的是,Bilbasen(手机优化版)的人们正在按照我的计划进行,并且对他们有效。
    • 这消除了三天的困惑。谢谢你。我希望修改 DllReferencePlugin 以盲目接受 manifest.json 文件中的内容。当清单中存在时,我认为不需要 webpack 来解决需求。
    【解决方案2】:

    你可以试试这个方法;

    new webpack.DllReferencePlugin({
      context: process.cwd(), // Important
      manifest: manifest.json
    }),
    

    【讨论】:

      猜你喜欢
      • 2016-03-29
      • 2017-04-05
      • 2017-09-17
      • 2016-11-04
      • 1970-01-01
      • 2015-07-09
      • 1970-01-01
      • 2016-04-21
      • 1970-01-01
      相关资源
      最近更新 更多