How to include npm modules in webpack libraries?

I am trying to use webpack DLL plugins (version 1.13) to create a DLL package that contains all the npm modules I need for various React projects (e.g. preact, preact-compat, redux, react-redux, redux saga, rebuild) . I want to distribute a DLL package containing all of these npm modules through the npm internal store. Several web applications must download the DLL package from npm replication and use the modules included in it.

In the example for using the DLL in webpack from the webpack repo on GitHub , a module named module included in the alpha DLL, module comes from the node_modules directory in the examples directory dir (one directory below dll dir).

This works when I create an example in dll-user dir using node build.js and watch dll-user/js/output.js , I can see these lines:

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

A module named module , however, is not a proper npm module, it is just a file called module.js located directly in the node_module directory. I tried to enable the "real world" module, in this case preact .

After creating the dll and dll-user projects, looking at the output.js file, I see that all the code of the preact module was included in the output, there is no delegation.

How to make this work right? Is this a bug in webpack?

I created a sample code on GitHub using the example of a DLL web package that shows the problem: https://github.com/pahund/webpack-dll-problem

+8
webpack
source share
1 answer

EDIT

Initially, I only did this example of work, but did not have a real idea how everything should be used. I wrote this (new content below the block):


Good, so I think I got at least some of this. I will tell you what you need to do to get your example working.

There are two ways to make it work:

  • Remove preact from package.json (and node_modules if necessary) of the folder containing , i.e. top level. Now you have preact only in the dll folder.
    Then change the call to require to example.js within the dll-user folder in
    require("../dll/node_modules/preact")
    This should work, but not quite what we want.

  • Now the opposite. Remove preact from the dll folder, but only install it in the folder containing it .
    Run both build scripts and see that everything is delegated in output.js , as it should include preact .


New:

Okay, so after I think a little, I think it works. (Since we know each other and work together with fewer words, but I think it can also help others if I give more details, so bear with me.)

Preliminary notes: I assume that you want to create a dll file that you 1) can install in the project using npm and 2) somehow include a script with your tag in your HTML. This script creates, when executed, a global variable that provides a function that, in turn, is used by your application script to resolve dependencies. In addition, I assume that you already have a directory for the dll set, configured only with package.json and webpack installed.

First you create webpack.config.js as follows:

 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) }) ] }; 

Now create the package and its manifest using

 $ webpack 

The dll project folder structure now:

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

Now you have installed this package in another project, your application:

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

This webpack.config.js looks (or similar):

 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") }) ] }; 

In your index.js , i.e. your application code, you need the modules that are in the dll package as follows:

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

If you run webpack -d , in the generated app.js you will see the following:

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

One may ask: "Why can not I use my standard, for example, require("preact") ?". Answer: you can, but. But in this case, you will have to install all these dependencies that you have with the dll, also in your application. Because in this case you will use the "display mode" instead of the "area mode" (see Webpack docs ).

In scope mode, you must explicitly specify require the module path relative to the manifest. Growth potential: you do not need to install the module (and have it as a dependency in package.json ) in your application.

In the displayed mode, you can require the module as usual (as if it were installed in your node_modules application), but you must also install it also in the dll using the application. This is because Webpack will first evaluate the call to require , and then realize that the same module is also in the dll package and thus only displays an alias ("delegated ...") in the output.


Now I think that in both modes service windows are used. The displayed mode is cool if you only create a local dll for applications to speed up your builds. In this case, you would still have to install and save all the fingerprints that enter the DLL locally. But if you want to create a dll package as an installable module and share it between applications - and you don’t want to keep track of all the modules in the dll in each of these applications - you most likely want to use a scope mode that pays the price of more detailed require calls.

+4
source share

All Articles