Why do some minified js files contain calls to "require" function - javascript

I've been modernizing some old gulp config where js files are concatenated and then minified by migrating to webpack.
Some of bundles contained libraries such as moment.js and isotope-docs.min.js,
When bundling with webpack I would get error that specific file or path is not found.
For example looking at moment.js
There is require("./locale/"+t) which causes my webpack to fail since i dont have locale directory.
Why would bundled js file have require function when browsers dont understand that?

Before ES modules became a thing, JavaScript did not have an official module syntax. Also, developers wanted to write a library once for both Node.js and the browser. The closest thing available was Node.js's require(), which does not exist on the browser.
So what tools like Browserify and Rollup would do is polyfill an implementation of require() (e.g. wrap the code in a "UMD"). This way, the module worked on any plaform and require() calls work as if in Node.js (its implementation may vary and can be extended because dealing with the filesystem is very different from dealing with a network).

Found a fix, you can just add to webpack confing under module noParse e.g
webpack.config.js
module: {
rules: [ ... ]
noParse: /moment.min.js|isotope-docs.min.js/
}

Related

How can I integrate custom module loading with webpack?

I'm using Webpack 1 for a frontend project and I have a legacy internal Javascript library which uses its own module system similar to AMD. A module is defined with a code similar to this:
MyLib.define('module id', ['my', 'module', 'deps'], function (my, module, deps) { /* module code */});
Then you can use the modules with a code like this:
MyLib.require(['dep1', 'dep2'], function (dep1, dep2) {});
I would like to be able to use MyLib along with all the other CommonJS modules I'm already using. Can webpack support this somehow?
As far as I know, Webpack doesn't support custom module formats (if someone else knows otherwise, I'd love to be proven wrong, though).
You perhaps could work around this by writing a Webpack loader or a Babel plugin that converts the syntax to one of the module formats that Webpack supports. The latter is what Babel used to do for ES6 imports before Webpack supported them out of the box - it'd just transform them into CommonJS require calls.

import requirejs amd module with webpack

I'm using Converse.js and it's prebuilt into the RequireJS/AMD syntax. Including the file from a CDN you could use it like require(['converse'], function (converse) { /* .. */ }). How is it possible to use this with webpack? I would like to bundle converse.js with my webpack output.
I have the file on disk, and want to import it like
import converse from './converse.js';
converse.initialize({ .. });
Webpack picks up the file and bundles it correctly, although it's not useable yet as it throws 'initialize is not a function'. What am I missing?
I suspect the way their bundle is built will not work correctly with how Webpack evaluates modules in a limited context.
From their builds, taking the built AMD module via NPM without dependencies should be parsable by Webpack and it will enable you to provide the dependencies to avoid dupes in the final output.
If all else fails, using the script-loader will evaluate the script in the global context and you'd get the same experience as if you'd have followed their usage guidelines to reference it from a CDN, just don't forget to configure the globals for your linter.

How do I export my browserified modules for requiring in the browser?

I have several js modules that I bundle with browserify in gulp:
gulp.task('build:js', ['clean:js'], function () {
browserify({
debug: true,
entries: paths.js.src
})
.transform('babelify', { presets: ['es2015'] })
.bundle()
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(gulp.dest(paths.js.dist));
});
It outputs a single bundle.js. However, when bundled like this I can't require individual modules in the browser. Which I'd like to do, because I don't want to always initiate every module (some are page specific). Instead of that I'd like to be able to use var someModule = require('some-module'); on a page alongside the bundle.
Now I couldn't really find anything about this in the documentation, since it only documents the commandline options (and not the js api). This answer shows that a module can be required and exposed from gulp, but that would expose my entire bundle, and not the modules of which it is composed.
A solution would be to bundle all my modules separately, exclude dependencies (so they won't be duplicated across bundles) and then concatenate that. But that doesn't really seem like a viable solution because:
The modules might have trouble resolving dependencies since everything is bundled separately, and thus dependencies would have to be resolved in-browser. Not ideal and prone to breakage I think.
It is very labour intensive since I use a lot of modules, and each will have to be exported manually in gulp, dependencies excluded and referenced in my templates. There are ways to automate it, but this doesn't exclude shared dependencies.
So how do I solve this? How can I require the bundles of which my js is composed separately in the browser, for client side use?
So what I ended up doing is something else. What I was asking kind of went against the way that browserify works, even though it's possible. Maybe eventually when HTTP2 imports and js modules can be used in all major browsers this'll be easier.
For now, I just have a global bundle for the scripts that run on every page, including all my third party libraries. And then for each page I have an separate entry point with the local modules that it needs. This is so far the most maintainable solution.

How to bundle legacy js files with webpack?

Suppose I have two files
a.js:
alert("hello from a.js");
b.js
alert("hello from b.js");
is there any way to bundle them with WebPack so that
I get both alerts synchronously as soon as bundle is loaded
alerts should be in the same order as declared
"hello from a" and then "hello from b"
Webpack natively supports CommonJS ( require / import ) and AMD style, and since yours are not falling into those categories, I believe you should look at the shimming modules section
https://github.com/webpack/docs/wiki/shimming-modules
This is from their header
In some cases webpack cannot parse some file, because it has a
unsupported module format or isn't even in a module format. Therefore
you have many options to convert the file into a module.
For anyone else that comes looking, the new (webpack 4+) link to the docs on shimming is here: https://webpack.js.org/guides/shimming/
For me personally, this webpack plugin was most helpful and headache free: https://www.npmjs.com/package/webpack-merge-and-include-globally

RequireJS tries to load webpack externals

Using Webpack, I'm exporting two distribution files for a project. One with dependencies bundled and one without.
Throughout the application, we use commonjs require('lodash.assign'); includes which webpack understands.
However, I've configured one of our builds to ignore these (for users who already use lodash and have it available).
externals = {
'lodash.assign': 'var _.assign',
'lodash.clonedeep': 'var _.cloneDeep'
};
This works as expected. However, because our libraryTarget is umd we support RequireJS. However, RequireJS still actually thinks these files should be loaded and I'm seeing a ton of errors:
require.min.js:1 GET http://127.0.0.1/_.assign.js req.load
# Uncaught Error: Script error for "_.assign"
It can't figure out where to find script. How can I configure webpack, or even requirejs to ignore these, since they're being mapped by webpack?
By looking at the compiled output, I see the reason requirejs thinks it's supposed to load these files:
define(["_.assign", "_.cloneDeep"], factory);
When I manually modify code to the following, it works:
define(['lodash'], factory);

Categories

Resources