首页 文章

如何在webpack DLL中包含npm模块?

提问于
浏览
10

我正在尝试使用webpack的DLL插件(版本1.13)创建一个DLL包,其中包含我需要的各种反应项目所需的所有npm模块(即preact,preact-compat,redux,react-redux,redux-saga) ,重新组合) . 我想通过我店的内部npm repo分发包含所有这些npm模块的DLL包 . 一些Web应用程序应该从npm repo加载DLL包并使用其中包含的模块 .

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

这有效,当我使用节点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模块的整个代码都包含在输出中,没有委托发生 .

How do I make this work properly? Is it a bug in webpack?

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

1 回答

  • 6

    EDIT

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


    好的,所以我认为我至少得到了它的一部分 . 我会告诉你为了让你的例子有效你必须做些什么 .

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

    • containing folder (即必要时 node_modules )中移除 preact ,即 containing folder ,即顶层 . 现在,您只在 dll 文件夹中有 preact .
      然后将 dll-user 文件夹中的 example.js 中的 require 调用更改为
      require("../dll/node_modules/preact")
      这应该有效但不完全是我们想要的 .

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


    New:

    好的,所以经过一些更多的探讨后,我觉得它的工作原理 . (因为我们彼此了解并且一起工作的次数会减少,但我认为如果我对细节更加明确,这也可能对其他人有所帮助,所以请耐心等待 . )

    初步说明:我假设您要创建一个dll文件,您可以使用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")
        })
      ]
    };
    

    在您的应用程序代码_1071639中,您需要以这种方式在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 ***!
      \***************************************************************************************************/
    

    有人可能会问:“为什么我不能像_1071644那样使用我的标准要求?” . 答案是:你可以,但是 . 但在这种情况下,您还必须在应用中安装dll包中的所有这些依赖项 . 因为在这种情况下,您将使用"mapped mode"而不是"scoped mode"(请参阅Webpack Docs) .

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

    在映射模式下,您可以照常使用该模块(就像它安装在您应用程序的node_modules中一样),但您还必须使用app在dll中安装它 . 这是因为Webpack将首先评估 require 调用,然后意识到同一模块也在dll包中,因此只在输出中呈现别名("delegated ...") .


    现在我认为这两种模式都有用例 . 如果你是的话,映射模式很酷只构建一个app-local dll来加速你的构建 . 在这种情况下,您将安装并保存所有本地进入dll的deps . 但是如果你想构建一个dll包作为可安装的模块并在应用程序之间共享它 - 并且你不想在每个这些应用程序中跟踪dll中的所有模块 - 你很可能想要使用作用域模式支付更详细的 require 电话的价格 .

相关问题