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

时间:2016-10-09 07:40:22

标签: webpack

我正在尝试使用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目录下方的一个目录)。

这很有效,当我使用node build.js在dll-user dir中构建示例并查看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中的错误吗?

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

2 个答案:

答案 0 :(得分:6)

修改

最初我只是让这个给定的例子工作,但没有真正的想法如何使用一切。我写了这个(块下面的新内容):

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

有两种方法可以使它发挥作用:

  1. 包含文件夹(即顶级)的preact(以及必要时package.json)中删除node_modules。现在,您只有preact文件夹中的dll
    然后更改requireexample.js内的dll-user来电 文件夹到 require("../dll/node_modules/preact")
    这应该有效但不完全是我们想要的。

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

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

    初步评论:我假设您要创建一个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")
        })
      ]
    };
    

    在您的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中安装它。这是因为Webpack将首先评估require调用,然后意识到同一模块也在dll包中,因此只将别名("委托...")呈现到输出中

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

答案 1 :(得分:0)

您可以尝试这种方式;

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