How to browserify a browserified module? - javascript

The title seems confusing but I'll give an example.
Let's say I create a module that uses ES6 that runs in the browser, so I use browserify with babelify to build everything.
Now I want to include that same module in a project that uses browserify, but does not uses Babel to compile ES6, so I need the compiled version.
I tried to require the "browserified" module like this:
// es5-project.js
require('./compiled-module-with-browserify');
But when I run browserify es5-project.js I start to get some errors like this:
Error: Cannot find module './XXX' from '/Users/mauricio.oliveira/projects/project-name/dist-folder'
And that makes sense, since browserify compiled all modules into one file, it won't find the modules inside the compiled file.
Does anyone have faced a problem like this one? if you did, how you solved it?
Thanks!

Found the answer!
This will do the trick https://github.com/substack/browserify-handbook#browser-field
Just define a "browser" index in the package.json file, and point to the initial source file.
:)

Related

Cannot use typescript class from other local typescript module using browserify

I have a common npm module containing TypeScript which is an node module providing some classes and functionality. This module is packaged via browserify + tsify and also exports the declaration files and built with gulp.
I have another npm module using TypeScript which imports this module locally via file:../modulename and tries to use functionality from the first module. The second module is also packaged via browserify + tsify and built with gulp. The compilation of the second module works via npx tsc, but fails if I execute the gulp build file with the error message
Error: Cannot find module './AbstractClass' from 'folderInOtherModuleContainingTheJSFiles'
Interestingly it sometimes fails with this Class sometimes with another, so it seems there is also some kind of concurrent processing.
I extracted the failing code from my project and created a minimal example with this behavior here.
npm version: 5.6.0
node version: v9.5.0
For anybody who might come to this post and face the same error.
I opened an issue at tsify too, thinking it has something to do with the plugin, because npx tsc worked.
Luckily the issue has been resolved, although with a workaround. There seems to be a name collision which causes browserify to think that a require call, which is a variable, in the resulting bundle needs to be resolved, but can't. The workaround is uglifying the resulting bundle, so that the conflict does not happen. More details in the above linked issue.

Mixing browserify and webpack externals

we are in the process of uplifting parts of a huge code base. We are bringing in a module which has been built with webpack. In order to avoid code duplication we have used webpacks externals option.
When we start to integrate our module into the main codebase which is currently using browserify, we have an issue where a shared dependency is included twice and causes issues.
Is there are a way to have webpack use the packaged version of the dependency? So in the final browserified bundle we just have the dependency included once?
It seems to me like this may not be possible, if so I will push for moving the rest of our codebase onto webpack (it is underway already).
The only solution I have come up with so far is to have the webpack module also export the shared dependency, and then have the main app use that export, but this is not ideal.
I have ensured that the dependency in both node_modules folders are at the same version and I still get 2 instances.
I need to be able to tell Browserify to only resolve my apps node_modules, or tell it to resolve from top to bottom, i.e. look in the top level node_modules first, is this possible?
I have tried setting the NODE_PATH option when using the cli to no affect.
** update **
So the issue is that when Browserify hits the require() statement in the webpack bundle it resolves from the local node_modules folder, so we end up with 2 instances of the dependency. I can fix this by using a relative path in either the apps require() or webpacks external option and ensuring they use the same file.
So it seems the issue was caused by the fact that I had symlinked (with npm link), the module as I was working on this also. It seems that when Browserify resolves the require in the symlinked module it resolves to its own node_modules, and we end up with 2 copies.
When I install the module normally it all works fine, so this is OK as other consumers of the module should have no issues. It is annoying that it behaves this way, but I just need to ensure that I point at the same dependency in my main app when developing alongside the module.
So my require statement in the main app (while symlinking) looks something like this:
require('./node_modules/my-module/node_modules/shared-dependency/index.js');
I can require as normal when not symlinking.

Why can't browserify use my module?

I made a library, bundled it with browserify, put it here: https://github.com/cfv1984/two-ways and published a module from it.
The library as compiled works just fine in the browser, the package I made from it is unusable as you can see by installing it and having a test file like this:
var two = require('two-ways');
console.log("Two", two);
And running it through
browserify test.file.js > test.compiled.js
What am I doing wrong? The error message I get, Error: Cannot find module './../../util/makeGetter' from 'D:\o\puto\node_modules\two-ways'makes 0 sense in this context, because I don't actually have a file in there any more, but a bundle, which as far as I can tell browserify was OK with generating.
Any pointers?
Browserify was mis-packing the file after transmogrifying it through Babel, so I simply used Webpack to package with which made it self-consistent again and I can use it with browserify and/or webpack or any other bundling software without much issue.

Building material-ui with browserify

I'm trying to build the material-ui (material-ui.com) javascript so that I can include it in my project and use the react components. I've been using browserify to bundle all the javascript into a single file, which I then include in my HTML file. So, in the material-ui/lib directory (which is where the JSX-transformed JS seems to live -- I'm very new to NPM bundles + browserify etc), I run
browserify index.js -o material-ui.js -r material-ui
I then include that material-ui.js file in my HTML.
But then when I try writing require('material-ui') in my javascript in the HTML page I get "Cannot find module 'material-ui'".
I don't really understand what browserify is meant to be doing, what the require function is doing, and how I'm meant to reference any of the material-ui react classes. Thanks!
So I just managed to solve this. Browserify was creating a require() function but not the material-ui module because I was calling it from the wrong directory. Calling it from the npm's module root without specifying a starting .js point somehow made it actually work, allowing me to use require('material-ui') without any errors.

How to create vendor bundles with latest Browserify (6.x.x)?

Well, we have been using Browserify 2.x for some time now. We are going through some refactoring so we want to try update to latest Browserify to diminish future leaps in versions.
Unfortunately something has changed in how external bundles are handled. In the old version we could simply tell Browserify which modules to keep out of the bundle and require them from another one - basically what is described here.
From the version 5.0.0 some big change in Browserify internals happened. Let's take for example this command. The debug module is NPM module.
browserify -r debug -o vendor.js
Running this command in Browserify#4, the output file would look like this:
require=(function... {
"debug":[function(require,module,exports){
module.exports=require('2Bvkwp');
},{}],
"2Bvkwp":[function(require,module,exports){
// actual code from debug module
},{}]
});
Now with the Browserify#5 it looks like this:
require=(function... {
1:[function(require,module,exports){
// actual code from debug module
},{}]
});
To complete the equation, I have simple file that contains require('debug') and this is bundled with command browserify -x debug -e index.js -o main.js. Internal dependency is set to undefined for the debug module, which is alright.
If you would look at the prelude.js file, there is logic that simply uses previously defined global require (stored in previousRequire variable) to find modules that are not defined within current bundle. BUT since vendor.js doesn't expose anything like debug module, it cannot succeed.
All I have been able to find is this line in the changelog:
hashing is gone so expose: true or explicit expose id is required for doing multi-export bundles
I am unable to find what does that actually means :(
You should able to create your vendor bundle like this:
browserify -r debug > vendor.js
And then create your application bundle like this:
browserify index.js -x debug > main.js
This works just fine (I'm using browserify#6.1.0).
Basically, even if require('debug'); won't work in the browser console, browserify can find the debug module in the vendor bundle as long as the bundles are loaded in the right order, i.e:
<script src="vendor.js"></script>
<script src="main.js"></script>
It doesn't have to expose the dependency to external code, only to other browserify bundles.

Categories