Browserify including entire module when only some parts used (react-addons) - javascript

I'm using Browserify to bundle serverside react.js code for the client.
However, I have a bad feeling that using a module from within an npm package results in that entire package being bundled by Browserify.
Q: Does require('react-addons').LinkedStateMixin result in the entire react-addons package being bundled into my Browserified JS?
IE: does Browserify treat require('react-addons').LinkedStateMixin the same as require('react-addons')?
If so, is there any way around this? External tools, Browserify options etc.

Browserify does not have the ability to extract parts of the functionality from a module.
What you can do though, is require the desired module from within react-addons like this:
require('react-addons/lib/LinkedStateMixin')
This will only include the one module (and it's dependencies) in your bundle. However, you now depend on the internal structure of the module. If the LinkedStateMixin is renamed, you will have to change your require statement.

#mantoni was helpful but as this is a react-addons specific question i will post my answer.
Don't use react-addons and react side by side. Instead, when requiring React use require('react/addons'). This calls a script at /addons/ that returns the full React with addons.
So for my example:
var React = require('react/addons');
var LinkedStateMixin = React.LinkedStateMixin;
//this works as normal!
React.createClass({});
Thanks guys!

In ReactJS 0.13.3 if you want to use e.g. CSSTransitionGroup you have to do the next:
var React = require('react/addons'),
CSSTransitionGroup = React.addons.CSSTransitionGroup;
And all that has to be installed – npm install react.

Related

How do I properly load the lit-html module in Electron

I'm trying to use lit-html to save my self some time, but I'm having trouble getting everything set up correctly.
Electron 4.1.1
Node 11.15
As of 5 minutes before posting this, I've run npm install and electron-rebuild, no luck.
I use require() as one would with any other NPM package
var render = require('lit-html').render
var html = require('lit-html').html
console.log(require("lit-html"))
Unfortunately, I'm greeted with this error
In reference to the three lines of code above.
I don't see any problems with my code.
I've tried reinstalling lit-html through NPM to no avail. I would really love to use this library, but first I have to get over this hurdle. If I'm being honest, I don't know if this error is reproducible, but nothing I do seems to fix it. The problem seems to lie with node and the way that imports are handled.
Am I missing something here? Is this a common issue? If so, what can I do to fix it?
You need to transpile lit-html before you can require it
I tested require('lit-html') and I was greeted with this error:
/home/chbphone55/Workspace/test/node_modules/lit-html/lit-html.js:31
import { defaultTemplateProcessor } from './lib/default-template-processor.js';
It clearly states that the error is coming from lit-html/lit-html.js:31 where the line uses ES Module import syntax.
You can transpile it using tools like Babel or similar ones. However, you may want to try using ES Module syntax so you can import lit-html without transpiling it.
Example:
<!-- HTML File -->
<script type="module" src="index.js"></script>
// index.js
import { html } from 'lit-html';
What if you can't use type="module"
If you are unable to use the type="module" method above, you can also use the ESM package.
ESM is a brilliantly simple, babel-less, bundle-less ECMAScript module loader.
Here are a few examples of how to use it:
Using the node require flag (-r) to load esm before everything else
node -r esm index.js
Loading esm in your main file then loading the rest of your code.
// Set options as a parameter, environment variable, or rc file.
require = require('esm')(module/*, options*/)
module.exports = require('./main.js')

How to create and publish a vue global function to NPM?

I know it sounds a bit confusing, but let me explain it here:
Right now there's a module that can be imported as CDN only:
<script src='https://www.example.com/example.min.js'></script>
after including it in index.html (or any .html file)
There's a few functions that can use from the module
<script>
$example_function.doSomething(param1,param2);
$example_function.doSomething2();
</script>
Because the module does not available as NPM package and for people like me want to use it in webpack built Vue.js project it's not so straight forward to use this module.
I know there's plenty of ways to workaround but I want it to be simple as I can just import it globally like other npm packages
import Example from 'example'
Vue.use(Example)
then I can call the function in any Vue components, or in my future vue projects.
Is it possible to achieve this?

Packaging sub-modules with rollup for node

I have a library (ES6) which is composed on many sub-modules, say
- package.json
- lib
- my_package
- file1.js
- file2.js
- sub_module1
- file3.js
- file4.js
I currently do imports like this (all inside my package - using file resolution to find, not node_modules resolution):
import {func1} from 'lib/my_package/file1'
import {func3} 'lib/my_package/sub_module1/file3'
So, in practice I have many files across sub-directories.
I am now trying to package and publish my library, which will be installed under node_modules.
It seems to me that the node resolution algorithm (when behind node_modules) only allows for a single entry point (and there is nothing rollup can do about that)
I would like to be able to include many sub directories and files and for them to be resolved individually.
As far as I understand I have to include a single toplevel file that has all the export from machinery. I can only import that single top level file.
This means having to manually create that file. It also means losing the all the sub-module name structuring that comes from the directory structure.
I was wondering: is there any way one can import any other file from a node_module directly?
Node's resolution algorithm only resolves the first part of a module source, so if someone does this...
var foo = require('your-library/subdir/foo.js');
...then Node (or Browserify/Webpack/rollup-plugin-node-resolve) will correctly resolve that to
/path/to/project/node_modules/your-library/subdir/foo.js
The tricky part is that you want to author JavaScript modules, but if someone is using your library in Node then they need CommonJS modules. Rollup can't help you here — you would need to do a one-to-one ESM->CJS conversion for each module. So that means either using Babel, or authoring CommonJS modules in the first place.

ES6 module import and dependency management

With the use of transpilers it is already possible to use ES6 modules. One of the easiest ways is using Browserify and Babelify.
The problem I'm having is how to handle dependency management.
In the old days you'd just have some Bower dependencies. The build would bundle non-CDN to vendor.js and project specific files to foobar.js (or whatever).
So then you'd be able to use the resulting code in a different project by simply bower install foobar --save.
If both foobar and your new project had a common dependency it would be easily resolved with Bowers flat dependency.
Now in come ES6 modules:
Say I have a project foo using lodash. The directory structure is as follows:
src/js/foo.js
src/vendor/lodash/dist/lodash.min.js
And foo.js starts by declaring:
import * as _ from '../../vendor/lodash/dist/lodash.min.js';
or (as Browserify wants since Babelify transpiles to CommonJS):
import * as _ from './../../vendor/lodash/dist/lodash.min.js';
If I now round up and publish my foo project and start a new project bar that uses foo this will be my directory structure.
src/js/bar.js
src/vendor/foo/dist/foo.js
src/vendor/lodash/dist/lodash.min.js
But that would not work since the path from foo to lodash is now broken (if I understand Browserify correctly the dot-slash in './blaat/file.js' is relative to the file it's being called from).
Is some way to import without making any file path assumptions?
Isn't there some way to indicate multiple source roots? (ie in the above case src/js and src/vendor ... well, ideally you'd just want to state import * as _ from 'lodash';)
I've only used Browserify with Babelify on cli. Should I be using some other transpiler?
I think that jspm is the solution your looking for. It will help you out without making file path assumptions when importing modules. It uses the SystemJS dynamic ES6 loader. Watch the video that is posted on their site for a very good explanation on how it all works, Guy Bedford: Package Management for ES6 Modules [JSConf2014].

How to import other javascript module in PhantomJS or CasperJS

I'm trying to build a functional test using CasperJS.
caseperjs is run by a backend test suite using the following command:
PHANTOMJS_EXECUTABLE=../client/node_modules/phantomjs/bin/phantomjs ../client/ext_modules/casperjs/bin/casperjs test ../client/test/functional/init.coffee
In init.coffee I want to import/include other module (file) which seats just next to it. How to do it?
The following doesn't works:
require("user")
All I want is to get a content from other file into init.coffee
After trying a number of the other suggestions (each expected to work in the context of their corresponding environments), hit on this solution:
phantom.page.injectJs( 'script.js');
As of 1.1, CasperJS relies on PhantomJS’ native require():
https://groups.google.com/forum/#!topic/phantomjs/0-DYnNn_6Bs
Injecting dependencies
While injecting additional modules, CasperJS looks for path relative to cur directory
(the place where we run a casperjs command)
We can inject dependency using clientScripts option. However the injected dependencies can't
use require "globally". They are injected immediately to every page loaded.
casper.options.clientScripts = ["path/relative/to/cur/dir"]
Also we can inject modules using commandline args:
casperjs test --includes=foo.js,bar.js path/to/the/test/file
Using require
To import user modules use:
require "./user-module.coffee"
Then in user modules you can also use require. Using require paths are resolved
relative to the current file (where require is called).
If in user module you want to import casper libs, then you need to patch require,
check: https://casperjs.readthedocs.org/en/latest/writing_modules.html
There's a section about that in the docs
var require = patchRequire(global.require);
require('./user');
In your case you should use global.require since you're using CoffeeScript.

Categories

Resources