I have made two bundles of javascript from our project- vendor and app. I do this in the manner suggested by the documentation, as seen in this snippet from my brunch-config.js:
files: {
javascripts: {
joinTo: {
'js/vendor.js': /^(?!source\/)/,
'js/app.js': /^source\//
},
entryPoints: {
'source/scripts/app.jsx': 'js/app.js'
}
}
}
And I end up with a vendor.js and an app.js. But check out the file sizes:
Note how app.js is larger than vendor.js! This large size makes watching slower than it needs to be. Upon inspecting the contents of app.js, it seemed to contain lodash, React, and other libraries, which I expected it to get from vendor.js. And vendor.js seems to contain the same libraries, which I do expect.
My question: Why are the libraries present in app.js? Why does app.js not reference them from vendor.js?
It is possible I missing some piece of configuration. Here is my full brunch-config.js for your examination:
module.exports = {
files: {
javascripts: {
joinTo: {
'js/vendor.js': /^(?!source\/)/,
'js/app.js': /^source\//
},
entryPoints: {
'source/scripts/app.jsx': 'js/app.js'
}
},
stylesheets: {joinTo: 'css/core.css'},
},
paths: {
watched: ['source']
},
modules: {
autoRequire: {
'js/app.js': ['source/scripts/app']
}
},
plugins: {
babel: {presets: ['latest', 'react']},
assetsmanager: {
copyTo: {
'assets': ['source/resources/*']
}
},
static: {
processors: [
require('html-brunch-static')({
processors: [
require('pug-brunch-static')({
fileMatch: 'source/views/home.pug',
fileTransform: (filename) => {
filename = filename.replace(/\.pug$/, '.html');
filename = filename.replace('views/', '');
return filename;
}
})
]
})
]
}
},
server: {
run: true,
port: 9005
}
};
and in HTML I require these files like this:
<script type="text/javascript" src="js/vendor.js" defer></script>
<script type="text/javascript" src="js/app.js" defer></script>
I tried setting the order object, but to no avail:
files:
javascripts: {
joinTo: {
'js/vendor.js': /^(?!source\/)/,
'js/app.js': /^source\//
},
entryPoints: {
'source/scripts/app.jsx': 'js/app.js'
},
order: {
before: /^(?!source)/,
after: /^source\//
}
}
}
Here's my package.json:
{
"version": "0.0.1",
"devDependencies": {
"assetsmanager-brunch": "^1.8.1",
"babel-brunch": "^6.1.1",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-rewire": "^1.0.0-rc-5",
"babel-plugin-transform-es2015-modules-commonjs": "^6.10.3",
"babel-plugin-transform-object-rest-spread": "^6.8.0",
"babel-preset-react": "^6.3.13",
"babel-register": "^6.11.6",
"browser-sync-brunch": "^0.0.9",
"brunch": "^2.10.9",
"brunch-static": "^1.2.1",
"chai": "^3.5.0",
"es6-promise": "^3.2.1",
"eslint-plugin-react": "^5.1.1",
"expect": "^1.20.2",
"html-brunch-static": "^1.3.2",
"jquery": "~2.1.4",
"jquery-mousewheel": "^3.1.13",
"mocha": "^3.0.0",
"nib": "^1.1.0",
"nock": "^8.0.0",
"oboe": "~2.1.2",
"paper": "0.9.25",
"path": "^0.12.7",
"pug": "^2.0.0-beta10",
"pug-brunch-static": "^2.0.1",
"react": "^15.2.1",
"react-dom": "^15.2.1",
"react-redux": "^4.4.5",
"redux": "^3.5.2",
"redux-logger": "^2.6.1",
"redux-mock-store": "^1.1.2",
"redux-promise": "^0.5.3",
"redux-thunk": "^2.1.0",
"reselect": "^2.5.3",
"spectrum-colorpicker": "~1.8.0",
"stylus-brunch": "^2.10.0",
"uglify-js-brunch": "^2.10.0",
"unibabel": "~2.1.0",
"when": "~3.4.5"
},
"dependencies": {
"jwt-decode": "^2.1.0",
"lodash": "^4.17.4",
"postal": "^2.0.5",
"rc-tree": "^1.3.9"
},
"scripts": {
"test": "mocha --compilers js:babel-register"
}
}
Another thought, could this have to do with using require
instead of import
?
If there's any other information I can provide that would be helpful please let me know. Thanks for your help.
UPDATE
Here's my folder structure, simplified:
node_modules
source
|---resources
|---scripts
|---styles
|---views
Here's the output structure produced by brunch build
:
assets
css
|---core.css
js
|---app.js
|---app.js.map
|---vendor.js
|---vendor.js.map
home.html
Debug it for yourself! MVCE available. Follow these instructions:
npm install
brunch build
(make sure it is installed globally with npm install brunch -g
)app.js
and vendor.js
in public/js
. They should be 744 KB and 737 KB respectively. Examine the contents of app.js and note the library stuff. How is my files.javascripts.joinTo['js/app.js']
including this with regex /^source\//
?The problem is caused by the mixture of joinTo
and entryPoints
. I assume that with your config, you first split your code in app.js
and vendor.js
but then the app.js
gets overridden by the output of the entryPoints
.
In order to solve it, you have to choose one of the options:
Option 1
Remove the entryPoints
declaration. This will just split your code along the provided RegEx.
Option 2
Remove the joinTo
declaration and change the entryPoints
to:
entryPoints: {
'source/scripts/app.jsx': {
'js/vendor.js': /^(?!source\/)/,
'js/app.js': /^source\//
},
}
Conclusion
In this very case, the output of both options is the same. But with entryPoints
the code get's analyzed and only needed modules get bundled. Because there aren't any unnecessary modules, the size is the same. See this issue for more information.