Effortless method for distributing NPM-loaded modules among various Browserify or Webpack bundles

Feeling frustrated trying to find a straightforward way to share code, required via NPM, across multiple Browserify or Webpack bundles. Is there a concept of a file "bridge" that can help?

I'm not concerned about compile time (I know about watchify), but rather I want to separate all vendor specific libraries into vendor.js to keep the size of my app.js down and prevent browser crashes from huge sourcemaps. It also makes it cleaner for viewing the compiled js code if needed. So here's what I have:

// vendor.js

require('react');
require('lodash');
require('other-npm-module');
require('another-npm-module');

It's crucial that the code is loaded from NPM rather than Bower or saved in a 'vendor' directory for import via relative paths and identification through a shim. I want every library reference to come from NPM except for my actual application source.

In app.js, I store all my source code, and using the externals array, exclude the vendor libraries mentioned above from compilation:

// app.js 

var React = require('react');
var _     = require('lodash');

var Component = React.createClass()

// ...

Then in index.html, I include both files:

// index.html
<script src='vendor.js'></script>
<script src='app.js'></script>

How can I enable app.js to access modules loaded via npm when using Browserify or Webpack? I know about creating a bundle with externals and then referencing the direct file (e.g., in node_modules) using an alias, but I'm looking for a more automatic solution that doesn't resemble Require.js.

In essence, I want to know if there's a way to bridge the two so that app.js can access the dependencies within vendor.js. It seems like a simple task, but I haven't been able to find an answer online. Any insight would be greatly appreciated!

Thanks!

Answer №1

It is highly recommended to list all vendor files/modules and utilize the CommonChunkPlugin. However, this process can become quite tedious and error-prone over time.

Take into consideration these NPM packages: fastclick and mprogress. Since they do not follow the CommonJS module format, webpack requires some manual intervention as shown below:

require('imports?define=>false!fastclick')(document.body);
require('mprogress/mprogress.min.css');
var Mprogress = require('mprogress/mprogress.min.js'),

If you desire both fastclick and mprogress in your vendor chunk, attempting the following may appear logical:

module.exports = {
  entry: {
    app: "./app.js",
    vendor: ["fastclick", "mprogress", ...]

Regrettably, this method does not work. The calls to require() must align as shown below:

module.exports = {
  entry: {
    app: "./app.js",
    vendor: [
      "imports?define=>false!fastclick", 
      "mprogress/mprogress.min.css", 
      "mprogress/mprogress.min.js", 
      ...]

Despite utilizing some resolve.alias trickery, this process becomes repetitive. Here's a workaround I suggest using. CommonChunkPlugin allows you to specify a callback function that determines whether a module should be included in the vendor chunk. If your source code resides in a specific src directory and everything else is in the node_modules directory, modules can be rejected based on their paths:

var node_modules_dir = path.join(__dirname, 'node_modules'),
    app_dir          = path.join(__dirname, 'src');

module.exports = {
  entry: {
    app: "./app.js",
  },
  output: {
    filename: "bundle.js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(
      /* chunkName= */"vendor",
      /* filename= */"vendor.bundle.js",
      function (module, count) {
       return module.resource && module.resource.indexOf(app_dir) === -1;
      }
    )
  ]
};

The value of module.resource is the module's path being considered. Alternatively, one could choose to include only modules within node_modules_dir, like so:

       return module.resource && module.resource.indexOf(node_modules_dir) === 0;

In my case, I prefer to state: "place everything outside my source tree in a vendor chunk".

I hope this explanation aids in your understanding.

Answer №2

By using webpack, you can implement multiple entry points along with the CommonChunkPlugin to split your code.

Referenced from the official webpack documentation:


If you want to divide your application into two separate files - let's say app.js and

vendor.js</code, then you should include the vendor files in <code>vendor.js
. Next, specify this name when utilizing the CommonChunkPlugin as illustrated below.

module.exports = {
  entry: {
    app: "./app.js",
    vendor: ["jquery", "underscore", ...],
  },
  output: {
    filename: "bundle.js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(
        /* chunkName= */"vendor",
        /* filename= */"vendor.bundle.js"
    )
  ]
};

This configuration will extract all modules within the vendor chunk and isolate them from the app chunk. Consequently, bundle.js will exclusively contain your application code, excluding any of its dependencies, which are now stored in vendor.bundle.js.

When loading these scripts in your HTML page, ensure that vendor.bundle.js is loaded before bundle.js.

<script src="vendor.bundle.js"></script>
<script src="bundle.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to capture the output of a script from an external website using Javascript when it is returning simple text?

Recently, I decided to incorporate an external script into my project. The script in question is as follows: <script type="application/javascript" src="https://api.ipify.org"> </script> This script is designed to provide the client's IP ...

The React component does not trigger a re-render

Using React Redux, I am able to pass values successfully. However, the component I intend to render only does so once. Interestingly, when I save my code in VSCode, it renders again and the data displays on the page as expected. return ( <div classN ...

Is there a feature in JavaScript that allows for the creation of URLs?

I created an index view displaying cards (like playing cards) in a grid using BootStrap. Each card is within its own div element, and I implemented a jQuery click handler for each div to open a details page when clicked. The redirect from the index to the ...

Having an issue with creating a React project using `npx`

Hey, whenever I attempt to run npx create-react-app appname, the process gets stuck and stops at reify:fsevents: sill reify mark deleted. Any idea what could be causing this issue and how to fix it? view screenshot here I've already tried clearing th ...

Error: Webpack is unable to locate the module ./lib/api/node.js when compiling the main

I decided to clean up my project by removing all node_modules and reinstalling them. Prior to the removal, everything was functioning smoothly. However, upon running webpack build, I encountered an error: https://i.stack.imgur.com/SF8ni.jpg In response, ...

"Encountering a 'react-scripts start' error while setting up on a different device

After creating a project on MacOS using "create react app" and committing it to Git, I am now facing an issue when cloning the folder on Windows. I have followed the usual steps: node npm npm install However, I encountered the following error: $ npm ...

Exploring the world of React and Material Ui

As I delve into working with Material Ui in React, I am encountering difficulties when trying to customize the components. For instance, let's take a look at an example of the AppBar: import React from 'react'; import AppBar from 'mat ...

Encountered an error in the React.js app where it cannot read the property 'Tag' of undefined from domhandler

I recently encountered an issue with my react.js project, which utilizes domhandler v4.2.0 through cheerio. Everything was running smoothly for months until one day, I started getting this error during the build process: domelementtype package includes a ...

Refresh numerous HTML <div>'s using data from a JSON object

Looking to automatically update the homepage of my website with the ten most recent "posts" from the server. Here's an example HTML format: <div id="post1"> <p id="link"> </p> </div> <div id="post2"> <p id="li ...

Is it possible to execute asynchronous queries within a map function in Mongoose?

Currently, I am struggling to create queries using a .map function, pushing the results to an array and then returning it. The issue is that the array always ends up empty due to the asynchronous nature of the operation. Although I attempted using async/ ...

Is there a way to prevent users from selecting certain days in ion-datetime?

After searching through the official documentation, I couldn't find a solution. I am in need of a function similar to the jQuery datepicker beforeshowday function. My goal is to disable all weekends (Saturday and Sunday) in upcoming dates so that user ...

`Strange interaction between request-json and bluebird promises`

I'm tackling the concept of promises, but I've hit a roadblock in getting a simple example to work. Here's a snippet of code for requesting JSON from the server: module.exports = function (app, options) { var promise = require('bluebi ...

Webpage video stalling due to buffering

Currently, I am developing personalized video controls and have integrated a @progress event to monitor the video buffering progress and adjust the width of a progress bar div: <video @progress="videoBuffer($event)"> videoBuffer(e) { if ...

How can I set up Node.js modules on a private LAN environment using NPM?

I'm currently working on setting up node.js on a LAN network that doesn't have internet access. Although I've successfully installed node.js, npm seems to require an internet connection to retrieve the modules I need. http GET <a href="h ...

Joomla website experiencing issues with Bootstrap popover functionality

Just wanted to share that I am currently working on this page: I found an example that inspired me from here: I have a feeling that Joomla might be including a resource that is causing conflicts with the popover not showing. This is the code snippet I h ...

How to message someone privately in a public Discord channel using discord.js

Can someone help me figure out how to create a message in discord.js version 12.5.3 that only I can see? I know how to send messages to channels using message.channel.send, but I'm not sure how to make a message visible only to myself. Thank you! ...

The node package for the 'browser' builder '@angular-devkit/build-angular' could not be located

My attempt at deploying my application to Heroku has hit a roadblock. While Heroku local web functions perfectly, I've encountered issues when trying to include 'npm i @angular-devkit/build-angular'. Despite scouring the internet for solutio ...

How can I transfer information from Node.js to Vue in an Nuxt.js server-side rendering setup?

I need to find a way to pass Firestore data to Vue files from Node.js (Express) because I have to utilize Firestore's getCollections() method, which cannot be executed on the client side. I have set up nuxt-ssr for deploying Google Cloud Functions an ...

How can I refresh the container with a new version of the file using PDFObject?

I'm having trouble with a button that generates a PDF and then reloads the PDF in the browser by replacing the container it's in, but with a different link. Despite my efforts, the new PDF does not show up and the old one remains even after refre ...

"Encountering a problem when trying to display Swagger-Editor for the second

While integrating the swagger-editor package into my React application, I encountered an issue. The first time I fetch the Swagger specifications from GitHub, everything works perfectly and validates correctly. However, upon rendering it a second time, an ...