webpack/README.md

259 lines
7.6 KiB
Markdown
Raw Normal View History

2012-03-10 20:11:23 +08:00
# modules-webpack
## Goal
As developer you want to reuse existing code.
As with node.js and web all file are already in the same language, but it is extra work to use your code with the node.js module system and the browser.
The goal of `webpack` is to bundle CommonJs modules into javascript files which can be loaded by `<script>`-tags.
2012-03-11 20:44:38 +08:00
Simply concating all required files has a disadvantage: many code to download (and execute) on page load.
Therefore `webpack` uses the `require.ensure` function ([CommonJs/Modules/Async/A](http://wiki.commonjs.org/wiki/Modules/Async/A)) to split your code automatically into multiple bundles which are loaded on demand.
2012-03-10 20:11:23 +08:00
This happens mostly transparent to the developer with a single function call. Dependencies are resolved for you.
The result is a smaller inital code download which results in faster page load.
**TL;DR**
2012-03-11 20:44:38 +08:00
* bundle CommonJs modules for browser
* reuse server-side code (node.js) on client-side
2012-03-10 20:11:23 +08:00
* create multiple files which are loaded on demand
* dependencies managed for you
* faster page load in big webapps
## Example
``` javascript
// a.js
var b = require("./b");
b.stuff("It works");
// b.js
exports.stuff = function(text) {
console.log(text);
}
```
are compiled to
``` javascript
(/* small webpack header */)
({
0: function(module, exports, require) {
var b = require(1);
b.stuff("It works");
},
1: function(module, exports, require) {
exports.stuff = function(text) {
console.log(text);
}
}
})
```
2012-03-11 20:44:38 +08:00
## Code Splitting
### Example
``` javascript
var a = require("a");
var b = require("b");
require.ensure(["c"], function(require) {
require("b").xyz();
var d = require("d");
});
```
```
File 1: web.js
- code of module a and dependencies
- code of module b and dependencies
File 2: 1.web.js
- code of module c and dependencies (but code is not used)
- code of module d and dependencies
```
2012-03-12 04:37:18 +08:00
See [details](modules-webpack/tree/master/examples/code-splitting) for exact output.
2012-03-11 20:44:38 +08:00
2012-03-10 20:11:23 +08:00
## Browser replacements
Somethings it happens that browsers require other code than node.js do.
`webpack` allow module developers to specify replacements which are used in the compile process of `webpack`.
Modules in `web_modules` replace modules in `node_modules`.
`filename.web.js` replaces `filename.js` when required without file extention.
TODO specify replacements in options
2012-03-12 04:37:18 +08:00
## require.context
If the `require`d module is not known while compile time we get into a problem.
A solution is the method `require.context` which takes a directory as parameter
and returns a function which behaves like the `require` function issued from a file
in this directory (but only if used for files in that directory).
### Example
We have a directory full of templates, which are compiled javascript files.
A template should be loaded by template name.
``` javascript
var requireTemplate = require.context("./templates");
function getTemplate(templateName) {
return requireTemplate("./" + templateName);
}
```
In addition to that `webpack` uses the `require.context` function automatically
if you use variables or other non-literal things in the `require` function.
That means the following code behaves like the above:
``` javascript
function getTemplate(templateName) {
return require("./templates/" + templateName);
}
// is compiled like: return require.context("./templates")("./"+templateName)
```
See [details](modules-webpack/tree/master/examples/require.context) for complete example.
*Warning: The complete code in the directory are included. So use it carefully.*
2012-03-10 20:11:23 +08:00
## Limitations
### `require`-function
As dependencies are resolved before running:
* `require` should not be overwritten
2012-03-12 04:37:18 +08:00
* `require` should not be called indirect as `var r = require; r("./a");`. Use `require.context`?
* `require.ensure` should not be overwritten or called indirect
2012-03-10 20:11:23 +08:00
* the function passed to `require.ensure` should be inlined in the call.
2012-03-12 04:37:18 +08:00
* `require.context` should not be overwritten or called indirect
* the argument to `require.context` should be a literal or addition of multiple literals
2012-03-10 20:11:23 +08:00
### node.js specific modules
As node.js specific modules like `fs` will not work in browser they are not included and cause an error.
You should replace them be own modules if your use them.
```
web_modules
fs
path
...
```
## Usage
### Shell
`webpack` offers a command line interface:
after `npm install webpack -g` you can use the `webpack` command
if invoked without arguments it prints a usage:
```
Usage: webpack <options> <input> <output>
Options:
--single Disable Code Splitting [boolean] [default: false]
--min Minimize it with uglifyjs [boolean] [default: false]
--filenames Output Filenames Into File [boolean] [default: false]
--options Options JSON File [string]
--script-src-prefix Path Prefix For JavaScript Loading [string]
--libary Stores the exports into this variable [string]
```
### Programmatically Usage
2012-03-11 20:44:38 +08:00
``` javascript
webpack(context, moduleName, [options], callback)
webpack(absoluteModulePath, [options], callback)
```
2012-03-10 20:11:23 +08:00
#### `options`
you can save this options object in a JSON file and use it with the shell command.
`outputJsonpFunction`
JSONP function used to load chunks
`scriptSrcPrefix`
Path from where chunks are loaded
`outputDirectory`
write files to this directory (absolute path)
`output`
write first chunk to this file
`outputPostfix`
write chunks to files named chunkId plus outputPostfix
`libary`
exports of input file are stored in this variable
`minimize`
minimize outputs with uglify-js
`includeFilenames`
add absolute filenames of input files as comments
#### `callback`
`function(err, source / stats)`
`source` if `options.output` is not set
2012-03-12 04:37:18 +08:00
else `stats` as json see [example](/modules-webpack/tree/master/examples/code-splitting)
2012-03-10 20:11:23 +08:00
## medikoo/modules-webmake
`webpack` as originally intended as fork for `webmake` for @medikoo so it shared several ideas with it.
So big credit goes to medikoo.
However `webpack` has big differences:
`webpack` replaces module names and paths with numbers. `webmake` don't do that and do resolves requires on client-side.
2012-03-12 04:37:18 +08:00
This design of `webmake` was intended to support variables as arguments to require calls.
2012-03-10 20:11:23 +08:00
`webpack` resolves requires in compile time and have no resolve code on client side. This results in smaller bundles.
Variables as argments will be handled different and with more limitations.
Another limitation in `webmake` which are based on the previous one is that modules must be in the current package scope.
In `webpack` this is not a restriction.
2012-03-12 04:37:18 +08:00
The design of `webmake` causes all modules with the same name to overlap.
This can be problematic if different submodules rely on specific versions of the same module.
The behaivior also differs from the behaivior of node.js, because node.js installs a module for each instance in submodules and `webmake` cause them the merge into a single module which is only installed once.
In `webpack` this is not the case.
Different versions do not overlap and modules are installed multiple times.
But in `webpack` this can (currently) cause duplicate code if a module is used in multiple modules.
I want to face this issue (TODO).
2012-03-10 20:11:23 +08:00
`webmake` do (currently) not support Code Splitting.
## Tests
You can run the unit tests which `node_modules/.bin/vows`.
You can run the browser tests:
```
cd test/browsertests
node build
```
and open `test.html` in browser. There must be several OKs in the file and no FAIL.
TODO more tests
## Contribution
You are welcome to contribute by writing issues or pull requests.
You are also welcome to correct any spelling mistakes or any language issues, because my english is not so good...
## License
MIT