umd-builder
v2.16.5
Published
Build modular client application with support of commonjs, requirejs and nodejs without duplicating source code
Downloads
105
Readme
umd-builder
This library is part of a bigger project developped for the following reasons:
- Test how much Asynchronous module definition (AMD) is slower than CommonJS module definition and up to which file size
- To have both module definitions without duplicating code and serve AMD files if the single page application file becomes too big
- To make debugging easier. A big javascript file is harder to debug that a small one even with source map
- To be able to reuse the same code with a nodejs server
- Because I have the feeling that as the project grows, a big javascript file may become a nuisance
Even though this library can be used as a replacement of [brunch], actually it can be seen as a customized version of brunch.
This library build a mix of CommonJS files and AMD files.
Project example
There is a project example in examples/project
Here is the project's structure
app/
assets/ // Files inside `assets` would be simply copied to `public` dir.
index.jst // Will be used to generate index.classic.html and index.single.html.
node_modules/
examples/ // Some files used by the application.
initialize.js // Application entry point.
server/
HttpServer.js // An http server that will
// serve index.classic.html when requesting /web.
// and serve index.single.html when requesting /app.
vendor/ // third party libraries needed.
.babelrc // babel configuration. Allows to parse jsx code.
.jshintrc // Some jshint rules.
bower.json // Describes which dependencies your client app uses.
brunch-config.coffee // Basic assumptions about the project, like paths & outputs.
build.js // cli for building. Usage is the same as brunch
package.json // Describes which dependencies and Brunch plugins your app uses.
test.js // Example of how to use generated files in nodejs
From project, issue
npm install
Build and start the server by issueing
node build.js w -s
In your favourite browser, navigate to
- http://127.0.0.1:3330/app to see the single page version
- http://127.0.0.1:3330/web to see the amd version
The application can also be viewed without starting a server by opening in your favourite browser
public/index.single.html
single page versionpublic/index.classic.html
amd version
Universal module definition (UMD) module file
A file is considered as an UMD module file if it has a top level function name factory
or freact
.freact
will make React
and ReactDOM
variables available.
Depencies of the module must be defined in a deps
variable.
UMD builder will look into all files that transformed in a javascript to check if they are UMD files
// app/node_modules/some/path/module.js
import relative from './relative'; // look for module defined in app/node_modules/some/path/relative.js
import forAll from 'for-all'; // look for module defined in app/node_modules/for-all.js. In nodejs, will use the classic require
import globalForAll from '!global-for-all'; // look for global variable global-for-all
import specificPerEnv from "%{ common: 'use-this-in-single-page-mode', amd: 'use-this-in-amd-mode', node: 'use-this-in-nodejs' }";
// in single page, look for global variable use-this-global-in-single-page-mode
// ignore other environments
import commonOnly from "%{ common: '!use-this-global-in-single-page-mode' }";
// Can also be used with require
// Dependency resolution will happend at runtime and the generated file will have a bigger overhead
// For that reason, use require only when you need computed dependencies
const nodeOnly = require({ node: "fs" });
// this require style is always supported
// it only loads modules asynchronously when in an AMD environment
// otherwise, it is just a wrapper for the commonjs require
require([ './relative', 'for-all', '!global-for-all', { node: "fs" }], (relative, forAll, globalForAll, nodeOnly) => {
// ...
});
Wild cards in bower.json file
When defining main, scripts or styles files in bower.json, you can use anymatch pattern.
The classic brunch do not allow that.
{
"jquery-ui": {
"main": [
"jquery-ui.js"
],
"styles": [
"themes/redmond/**"
],
"scripts": [
"ui/version.js",
"ui/keycode.js",
"ui/widgets/datepicker.js",
"ui/i18n/datepicker-ar.js",
"ui/i18n/datepicker-fr.js",
"ui/i18n/datepicker-he.js",
"ui/i18n/datepicker-zh-TW.js"
]
}
}
Deal with traditional "browser globals" scripts
Configure the dependencies, exports, and custom initialization for older, traditional "browser globals" scripts that do not use define() to declare the dependencies and set a module value.
{
"bootstrap": {
"main": [
"dist/css/bootstrap.css",
"dist/js/bootstrap.js",
"dist/fonts/**"
],
"dependencies": {
"jquery": "*"
},
"exports": "jQuery.fn.emulateTransitionEnd"
}
}
Compilers
With the classic brunch, the only way to add a compiler is to delacre it in package.json.
That is too restrictive for me for 3 reasons:
- First, I am too lazy to always create an npm package when I am testing stuff
- Second, I am also too lazy to spend time to find a way to try completely separate my custom compilers from umd-builder package
- Third, the benefits of being lazy seem to me far greater than the benefits of having a package
For those reasons, I made a way to add compilers directly in brunch-config file.
Nevertheless, if I am aware of better benefits than being lazy, I will spend time to try to make things cleaner.
AmdCompiler
Depends on umd-builder.
Mandatory. Transform files with a top level factory or freact function in umd module.
exports.config =
compilers: [
require('umd-builder/lib/compilers/amd')
]
plugins:
amd:
strict: true # add 'use strict' in module definition (factory or freact)
jshint: true # lint generated javascript using jshint
jshint:
warnOnly: true # if false, failed linted will be considered as error
# ignore: ignore # function(path) called to determined if file should be linted.
# Usually, third party libraries should be ignored
# options: {} # if defined, ignore rules defined in .jshintrc
CopyCompiler
Depends on umd-builder.
Recommended. Copy all watched files that do not match a javascript or stylesheet compiler.
Usefull for images, fonts required in stylesheets.
exports.config =
compilers: [
require('umd-builder/lib/compilers/copy')
]
RelativeCSS
Depends on umd-builder.
Recommended. Keep correct path in css. ex: bootstrap.
Usefull for images, fonts required in stylesheets.
exports.config =
compilers: [
require('umd-builder/lib/compilers/relativecss')
]
BabelCompiler
Transform every javascript code using babel.
exports.config =
compilers: [
require('umd-builder/lib/compilers/babel')
]
plugins:
babel:
# optional transformations
pretransform: [
[
# add spModel, spClick, spShow, ... more details later
require('umd-builder/lib/spTransform'), {transformations: mdl: false}
]
]
# ignore: ignore # function(path) called to determined if file should be transform with babel.
# Usually, third party libraries should be ignored
# if no other option is setted, use rules defined rules in .babelrc
HandlebarsCompiler
Transform handlebars files into UMD modules
Similar to handlebars-brunch.
At the time I started this library, handlebars-brunch was not using the latest version of handlebars and I was using handlebars the new features.
exports.config =
compilers: [
require('umd-builder/lib/compilers/handlebars')
]
HtmlCompiler
Transform html and htm files into UMD modules.
exports.config =
compilers: [
require('umd-builder/lib/compilers/html')
]
JstCompiler
Transform jst files into UMD modules that expose a lodash template.
I added an ignore option to use comments in files.
<%
is to be able to use Java Server Page (JSP) syntax highlight in sublime text and notepad++ since Java is not far from Javscript.
exports.config =
compilers: [
require('umd-builder/lib/compilers/jst/jst')
]
plugins:
jst:
# _.template uses with when no variable is given. Since with is not recommended on MDN, I prefer not to use it
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with
variable: 'root'
ignore: /<%--([\s\S]+?)--%>/g # added for comments within templates
escape: /<%-([\s\S]+?)%>/g # default value
interpolate: /<%=([\s\S]+?)%>/g # default value
evaluate: /<%([\s\S]+?)%>/g # default value
strict: true
MarkdownCompiler
Transform markdown files into UMD modules
exports.config =
compilers: [
require('umd-builder/lib/compilers/markdown')
]
plugins:
# https://github.com/chjj/marked
# defined maked options
markdown:
jst: false # Allow interpertation of javascript code within jst brackets. Look at JstCompiler for more details
# example: You can follow the [tutorial](<%= app.router.engine('default').getUrl({module: 'tutorial', controller: 'home', action: 'step0'}) %>)
StylusCompiler
Transform stylus files into stylesheet files.
I don't remember why I created this since there is stylus-brunch that does the same job.
exports.config =
compilers: [
require('umd-builder/lib/compilers/stylus')
]
Known issues
Partial build for large projects
It is hard to define large projet, let's say a project on which copy all files (app, bower_components, vendor) will take more than 60 seconds.
With those kind of projects, sometimes, build does not start correctly.
Re-run the build in those cases.
Because there is a workaround and not easy to reproduce, I don't want to spend time trying to fix it.
Source maps
With all those transformations, I have difficulties keeping the source map correct. The truth is, I don't understand a thing about source maps.
License
The MIT License (MIT)
Copyright (c) 2014-2018 Stéphane MBAPE (http://smbape.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.