Split vendor libraries into multiple chunks with webpack - javascript

I'd like to split my vendor code into two chunks, one that contains all angular libraries, and another that contains everything else.
My angular app has a single entry point and is setup something like:
entry: {
app: './path_to/app.js',
vendor: ['jquery', 'moment', 'numeral'],
'vendor.angular': ['angular', 'angular-route', 'angular-numeraljs']
}
I then use the CommonsChunkPlugin to configure the two other bundles:
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
chunks: ['app'],
warnings: false,
filename: 'vendor.bundle.js'
})
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor.angular',
chunks: ['app'],
warnings: false,
filename: 'vendor.angular.bundle.js'
})
This generates 3 files:
Version: webpack 1.13.1
Time: 12719ms
Asset Size Chunks Chunk Names
app.bundle.js 19.2 kB 0 [emitted] app
vendor.bundle.js 484 kB 1 [emitted] vendor
vendor.angular.bundle.js 652 kB 2 [emitted] vendor.angular
[0] multi vendor.angular 124 bytes {2} [built]
[0] multi vendor 88 bytes {1} [built]
+ 124 hidden modules
app.bundle.js contains just my app code.
vendor.bundle.js contains all 3rd party libs excluding angular stuff
vendor.angular.bundle.js contains all angular stuff AND all my 3rd party libs that are already inside of vendor.bundle.js.
Is there anyway to have JUST the angular modules bundled in vendor.angular.bundle.js, without automatically including the other 3rd party libs?

Figured this out:
The order of the CommonsChunkPlugin's matter in the plugins array.
To get the desired 'chunking', here's the change I had to make:
Re-order the CommonsChunkPlugins so that the angular chunk was
first.
Update the 'vendor' config below to use 'vendor.angular' in the 'chunks' array.
The updated CommonsChunkPlugins now looks like:
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor.angular',
chunks: ['app'],
warnings: false,
filename: 'vendor.angular.bundle.js'
})
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
chunks: ['vendor.angular'],
warnings: false,
filename: 'vendor.bundle.js'
})
The above now yields:
Version: webpack 1.13.1
Time: 7451ms
Asset Size Chunks Chunk Names
app.bundle.js 19.2 kB 0 [emitted] app
vendor.bundle.js 484 kB 1 [emitted] vendor
vendor.angular.bundle.js 221 kB 2 [emitted] vendor.angular
[0] multi vendor.angular 124 bytes {2} [built]
[0] multi vendor 88 bytes {1} [built]
+ 124 hidden modules
Running:
webpack --progress --display-modules --display-chunks -v
I'm able to verify that all angular related modules are now in the vendor.angular.bundle.js, and all non-angular modules are indeed in vendor.bundle.js

Related

Why won't webpack ignore my node_modules?

I have tried configuring it multiple ways and reduced the config file to a bare minimal but it always compiles my node_modules folder.
I have tried using a regular expression as seen below, as well as inserting the direct path.
Webpack requires direct paths which I am using instead of the path module for clarity.
Webpack config file
// style-loader and css-loader are both required to handle .css files
const css = {
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
};
// babel-loader handles .js and .jsx files
const jsx = {
test: /\.jsx?/,
exclude: [
/node_modules/
],
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
}
};
// this webpack configuration file supports these two file types
const file_types = {
rules: [
css,
jsx
]
};
const input = '/Users/c/top/frame/index.jsx';
const output = {
filename: 'bundle.js',
path: '/Users/c/top/frame-server/dist'
};
const stats = { warnings: true };
// combine above objects and export
const config_obj = {
stats: stats,
entry: input,
output: output,
module: file_types
};
module.exports = (env) => {
return config_obj;
};
Yet still I see them compiled:
asset bundle.js 209 KiB [compared for emit] [minimized] (name: main) 1 related asset
orphan modules 787 KiB [orphan] 460 modules
runtime modules 663 bytes 3 modules
cacheable modules 375 KiB
modules by path ./node_modules/ 155 KiB 22 modules
modules by path ./A1People/ 4.31 KiB 6 modules
modules by path ./F1PageUser/ 4.9 KiB 5 modules
modules by path ./F1Apex/ 2.87 KiB 4 modules
modules by path ./A1Article/ 3.43 KiB 4 modules
modules by path ./F1M1/ 2.9 KiB 4 modules
modules by path ./C0Images/ 2.02 KiB 3 modules
modules by path ./C2Menu/ 2.04 KiB 3 modules
modules by path ./C3BarAdmin/ 1.56 KiB
./node_modules/css-loader/dist/cjs.js!./C3BarAdmin/C3BarAdmin.css 504 bytes [built] [code generated]
+ 2 modules
+ 8 modules
webpack 5.69.1 compiled with 2 warnings in 6635 ms
I am following the documentation by webpack found here.
and version as follows:
"webpack": "^5.69.1",
"webpack-cli": "^4.9.2"
I am getting a strange warning but I don't know if it is relevant:
WARNING in ./node_modules/React/cjs/react.production.min.js
There are multiple modules with names that only differ in casing.
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:
* /Users/c/top/frame/node_modules/React/cjs/react.production.min.js
Used by 1 module(s), i. e.
/Users/c/top/frame/node_modules/React/index.js
* /Users/c/top/frame/node_modules/react/cjs/react.production.min.js
Used by 1 module(s), i. e.
/Users/c/top/frame/node_modules/react/index.js
# ./node_modules/React/index.js 4:2-59
# ./F1PageUser/ULogin.jsx 2:0-26 5:22-41 7:18-37 9:18-37 11:31-50
# ./F1PageUser/User.jsx 4:0-34 14:47-53
# ./F1Page/F1Page.jsx 8:0-44 21:57-63
# ./F1/F1.jsx 5:0-42 18:184-190
# ./index.jsx 8:0-29 12:36-38

Webpack bundle size increases on every consecutive build

I'm packing a project with webpack in order to use it as a library. It's a components library so I'm generating small bundles for every component that lives in its own directory under src/ui. This is a example component:
src/
|- ui/
|-- anchor/
|- dist/
|- index.js
|- _anchor.scss
I pretend to generate the bundled component in dist/index.js.
With my current Webpack configuration, if I run NODE_ENV=production webpack --display-modules for example, three consecutive times wihtout changing any code, the Webpack outputs are:
Asset Size Chunks Chunk Names
anchor/dist/index.js 4.69 KiB 0 [emitted] anchor
anchor/dist/index.js.map 15.8 KiB 0 [emitted] anchor
Entrypoint anchor = anchor/dist/index.js anchor/dist/index.js.map
[0] external "react" 42 bytes {0} [built]
[1] external "classnames" 42 bytes {0} [built]
[2] ./src/ui/anchors/_anchor.scss 1.94 KiB {0} [built]
[3] ./node_modules/css-loader/dist/runtime/api.js 2.35 KiB {0} [built]
[4] ./src/ui/anchor/index.js + 1 modules 1.69 KiB {0} [built]
| ./src/ui/anchor/index.js 1.41 KiB [built]
| ./node_modules/babel-preset-react-app/node_modules/#babel/runtime/helpers/esm/defineProperty.js 269 bytes [built]
Asset Size Chunks Chunk Names
anchor/dist/index.js 5.7 KiB 0 [emitted] anchor
anchor/dist/index.js.map 14.3 KiB 0 [emitted] anchor
Entrypoint anchor = anchor/dist/index.js anchor/dist/index.js.map
[0] ./src/ui/anchor/dist/index.js 4.69 KiB {0} [built]
[1] external "react" 42 bytes {0} [built]
[2] external "classnames" 42 bytes {0} [built]
Asset Size Chunks Chunk Names
anchor/dist/index.js 6.71 KiB 0 [emitted] anchor
anchor/dist/index.js.map 16.6 KiB 0 [emitted] anchor
Entrypoint anchor = anchor/dist/index.js anchor/dist/index.js.map
[0] ./src/ui/anchor/dist/index.js 5.7 KiB {0} [built]
[1] external "react" 42 bytes {0} [built]
[2] external "classnames" 42 bytes {0} [built]
As you can see, bundle size increases around a 1 KiB on each execution.
My current webpack configuration is:
const path = require('path')
module.exports = {
mode: 'production',
entry: {
anchor: './src/ui/anchor'
},
output: {
path: path.resolve(__dirname, 'src', 'ui'),
filename: '[name]/dist/index.js',
library: ['components', '[name]'],
libraryTarget: 'umd'
},
externals: {
react: 'umd react',
'react-dom': 'umd react-dom',
'prop-types': 'umd prop-types',
classnames: 'umd classnames'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|dist)/,
loader: 'babel-loader',
options: {
presets: [require.resolve('babel-preset-react-app')],
},
enforce: 'pre',
}, {
test: /\.scss$/,
use: [
"css-loader",
"sass-loader"
]
}
]
},
devtool: 'source-map'
}
How can I configure it so bundle 'resets' or stays the same?
In library.filename, you configured the [name] option specifying for every entry you have configured, it'll assign a special name. You would usually only use this parameter if you are using multiple entry points, which I don't see here.
You shouldn't have to "reset" anything when you recompile your Webpack. I'm guessing the file size didn't get infinitely larger after this question, right?
Check this out:
https://github.com/webpack/webpack/tree/master/examples/multi-part-library

Webpack - WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB)

When I run webpack in production mode.
There is a warning that asset size limit (exceed).
How can I run without this error?
In my project, I include css, and I see some node_module directory include in the webpack build.
But if I exclude node_module of css it will have the error.
The following is the output when I try to build my project with webpack.
[mai#localhost dssoft]$ yarn run build
yarn run v1.9.2
$ webpack --config webpack.config.js
Hash: a5edfb917e6152759218
Version: webpack 4.16.3
Time: 16592ms
Built at: 08/07/2018 7:58:40 PM
Asset Size Chunks Chunk Names
f4769f9bdb7466be65088239c12046d1.eot 19.7 KiB [emitted]
448c34a56d699c29117adc64c43affeb.woff2 17.6 KiB [emitted]
fa2772327f55d8198301fdb8bcfc8158.woff 22.9 KiB [emitted]
e18bbf611f2a2e43afc071aa2f4e1512.ttf 44.3 KiB [emitted]
89889688147bd7575d6327160d64e760.svg 106 KiB [emitted]
bundle.js 624 KiB 0 [emitted] [big] main
Entrypoint main [big] = bundle.js
[22] ./node_modules/react-router-dom/es/index.js + 34 modules 80.3 KiB {0} [built]
| 35 modules
[29] ./node_modules/react-bootstrap/es/index.js + 104 modules 301 KiB {0} [built]
| 105 modules
[90] ./js/reducers/index.js 650 bytes {0} [built]
[116] ./node_modules/react-redux/es/index.js + 23 modules 43 KiB {0} [built]
| 24 modules
[121] multi whatwg-fetch ./js/App.js 40 bytes {0} [built]
[122] ./js/App.js 5.17 KiB {0} [built]
[134] ./js/actions/index.js 2.31 KiB {0} [built]
[213] ./js/configureStore.js 1.4 KiB {0} [built]
[221] ./js/pages/Index.js 479 bytes {0} [built]
[222] ./js/pages/Signup.js 8.04 KiB {0} [built]
[227] ./js/pages/Login.js 7.67 KiB {0} [built]
[228] ./js/pages/Logout.js 620 bytes {0} [built]
[229] ./js/pages/NotFound.js 2.86 KiB {0} [built]
[230] ./js/pages/Events.js 3.51 KiB {0} [built]
[244] ./js/App.css 1.04 KiB {0} [built]
+ 231 hidden modules
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
bundle.js (624 KiB)
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
main (624 KiB)
bundle.js
WARNING in webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
Done in 20.99s.
Additional webpack.config.js
const path = require('path');
module.exports = {
mode: 'production',
entry: [
'whatwg-fetch',
path.resolve(__dirname, 'src', 'App.js')
],
module: {
rules: [
{
test: /\.js$/,
exclude: /\/node_modules\//,
use: {
loader: 'babel-loader',
}
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
loader: 'url-loader',
options: {
limit: 10000
}
}
]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public'),
},
};
Webpacks warning size seems out of date. Instead of just ignoring it you can set it to a more meaningful size limit.
module.exports = {
....
},
performance: {
maxEntrypointSize: 512000,
maxAssetSize: 512000
},
....
}
You can hide these warnings/hints by setting performance.hints = false:
{
performance: {
hints: false
}
}
See the docs for more information.
Of course, the hint is there for a reason and you should look into ways of reducing your bundle size. For example by using code splitting.
performance: {
hints: false
}
hide by this statement

bin/webpack error while introducing VueJS to Rails app

I'm trying to introduce Vue.JS by webpack. Now I'm struggling with an error while I execute bin/webpack.
The issue is similar to this one (Can't use vue component in my Rails5 app) but seems slightly different, as nothing will be changed if I remove tag in "/app/javascript/app.vue".
The gem file is below:
gem 'webpacker', github: 'rails/webpacker'
And the below is "/config/webpack/webpacker.yml":
# Note: You must restart bin/webpack-dev-server for changes to take effect
default: &default
source_path: app/javascript
source_entry_path: packs
public_output_path: packs
cache_path: tmp/cache/webpacker
# Additional paths webpack should lookup modules
# ['app/assets', 'engine/foo/app/assets']
resolved_paths: []
# Reload manifest.json on all requests so we reload latest compiled packs
cache_manifest: false
extensions:
- .vue
- .js
- .sass
- .scss
- .css
- .module.sass
- .module.scss
- .module.css
- .png
- .svg
- .gif
- .jpeg
- .jpg
development:
<<: *default
compile: true
# Reference: https://webpack.js.org/configuration/dev-server/
dev_server:
https: false
host: localhost
port: 3035
public: localhost:3035
hmr: false
# Inline should be set to true if using HMR
inline: true
overlay: true
compress: true
disable_host_check: true
use_local_ip: false
quiet: false
headers:
'Access-Control-Allow-Origin': '*'
watch_options:
ignored: /node_modules/
test:
<<: *default
compile: true
# Compile test packs to a separate directory
public_output_path: packs-test
production:
<<: *default
# Production depends on precompilation of packs prior to booting for performance.
compile: false
# Cache manifest.json for performance
cache_manifest: true
Error:
$ bin/webpack
(node:24139) ExperimentalWarning: The fs.promises API is experimental
Hash: 609c54cf56c50ef7c14a
Version: webpack 3.12.0
Time: 1760ms
Asset Size Chunks Chunk Names
hello-3fc5abe86ea1eca80c8f.js 248 kB 0 [emitted] hello
application-12a437e15157c0d4029c.js 3.27 kB 1 [emitted] application
hello-9cb5a7334a6577c3422968b9b9970b2f.css 134 bytes 0 [emitted] hello
hello-3fc5abe86ea1eca80c8f.js.map 293 kB 0 [emitted] hello
hello-9cb5a7334a6577c3422968b9b9970b2f.css.map 557 bytes 0 [emitted] hello
application-12a437e15157c0d4029c.js.map 3.19 kB 1 [emitted] application
manifest.json 402 bytes [emitted]
[0] (webpack)/buildin/global.js 509 bytes {0} [built]
[1] ./app/javascript/app.vue?vue&type=script&lang=js 362 bytes {0} [built]
[2] ./node_modules/babel-loader/lib??ref--1-0!./node_modules/vue-loader/lib??vue-loader-options!./app/javascript/app.vue?vue&type=scrip
t&lang=js 1.66 kB {0} [built] [failed] [1 error]
[3] ./node_modules/extract-text-webpack-plugin/dist/loader.js??ref--1-0!./node_modules/style-loader??ref--4-1!./node_modules/css-loader
??ref--1-2!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/lib??ref--1-3!./node_modules/vue-loader/
lib??vue-loader-options!./app/javascript/app.vue?vue&type=style&index=0&id=6fb8108a&scoped=true&lang=css 41 bytes {0} [built]
[4] ./app/javascript/packs/application.js 515 bytes {1} [built]
[5] ./app/javascript/packs/hello.js 1.93 kB {0} [built]
[10] ./app/javascript/app.vue 978 bytes {0} [built]
[11] ./app/javascript/app.vue?vue&type=template&id=6fb8108a&scoped=true 212 bytes {0} [built]
[12] ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./app
/javascript/app.vue?vue&type=template&id=6fb8108a&scoped=true 749 bytes {0} [built]
[13] ./app/javascript/app.vue?vue&type=style&index=0&id=6fb8108a&scoped=true&lang=css 896 bytes {0} [built]
+ 5 hidden modules
ERROR in ./node_modules/babel-loader/lib??ref--1-0!./node_modules/vue-loader/lib??vue-loader-options!./app/javascript/app.vue?vue&type=scr
ipt&lang=js
Module build failed: ReferenceError: [BABEL] /Users/hogehoge//app/javascript/app.vue: Unknown option: base.omit. C
heck out http://babeljs.io/docs/usage/options/ for more information about options.
A common cause of this error is the presence of a configuration options object without the corresponding preset name. Example:
Invalid:
`{ presets: [{option: value}] }`
Valid:
`{ presets: [['presetName', {option: value}]] }`
For more detailed information on preset configuration, please see https://babeljs.io/docs/en/plugins#pluginpresets-options.
at Logger.error (/Users/hogehoge/node_modules/babel-core/lib/transformation/file/logger.js:41:11)
at OptionManager.mergeOptions (/Users/hogehoge/node_modules/babel-core/lib/transformation/file/options/option
-manager.js:226:20)
at OptionManager.init (/Users/hogehoge/node_modules/babel-core/lib/transformation/file/options/option-manager
.js:368:12)
at File.initOptions (/Users/hogehoge/node_modules/babel-core/lib/transformation/file/index.js:212:65)
at new File (/Users/hogehoge/node_modules/babel-core/lib/transformation/file/index.js:135:24)
at Pipeline.transform (/Users/hogehoge/node_modules/babel-core/lib/transformation/pipeline.js:46:16)
at transpile (/Users/hogehoge/node_modules/babel-loader/lib/index.js:50:20)
at Object.module.exports (/Users/hogehoge/node_modules/babel-loader/lib/index.js:173:20)
# ./app/javascript/app.vue?vue&type=script&lang=js 1:0-172 1:193-362
# ./app/javascript/app.vue
# ./app/javascript/packs/hello.js
ERROR in ./node_modules/extract-text-webpack-plugin/dist/loader.js??ref--1-0!./node_modules/style-loader??ref--4-1!./node_modules/css-load
er??ref--1-2!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/lib??ref--1-3!./node_modules/vue-loade
r/lib??vue-loader-options!./app/javascript/app.vue?vue&type=style&index=0&id=6fb8108a&scoped=true&lang=css
Module build failed: ValidationError: Style Loader Invalid Options
options['ident'] is an invalid additional property
# ./app/javascript/app.vue?vue&type=style&index=0&id=6fb8108a&scoped=true&lang=css 1:0-439 1:460-896
# ./app/javascript/app.vue
# ./app/javascript/packs/hello.js
Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/index.js??ref--1-2!node_modules/vu
e-loader/lib/loaders/stylePostLoader.js!node_modules/postcss-loader/lib/index.js??ref--1-3!node_modules/vue-loader/lib/index.js??vue-loade
r-options!app/javascript/app.vue?vue&type=style&index=0&id=6fb8108a&scoped=true&lang=css:
[0] ./node_modules/css-loader??ref--1-2!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/lib?
?ref--1-3!./node_modules/vue-loader/lib??vue-loader-options!./app/javascript/app.vue?vue&type=style&index=0&id=6fb8108a&scoped=true&lang=c
ss 789 bytes {0} [built]
+ 1 hidden module
If you have any advice that would be so helpful.

Apply loader to specific file

I'm following http://alexomara.com/blog/webpack-and-jquery-include-only-the-parts-you-need to bundle parts of jQuery using webpack.
// webpack.config.js
module.exports = {
entry: './entry',
output: {
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /jquery\/src\/selector\.js$/,
loader: 'amd-define-factory-patcher-loader'
}
]
}
};
It turns out that node_modules/jquery/src/selector.js needs it own loader due to an AMD issue. But the loader is not being applied. I'm running under windows and maybe the regexp needs to be adjusted? I tried different expressions but no luck.
Any suggestions on how to debug? New to webpack.
As suggested, I added:
profile: true,
stats: {
reasons: true,
chunkModules: true,
chunkOrigins: true,
modules: true,
cached: true,
cachedAssets: true,
source: true,
errorDetails: true,
publicPath: true,
excludeModules: [
/e\.js/
]
Running webpack --display-modules yields
Hash: 4a092c0d4d9e158a9bd7
Version: webpack 1.10.1
Time: 970ms
Asset Size Chunks Chunk Names
bundle.js 876 kB 0 [emitted] main
[0] ./entry.js 529 bytes {0} [built]
factory:13ms building:12ms = 25ms
...
[14] ./~/jquery/src/traversing/var/rneedsContext.js 110 bytes {0} [built]
[0] 25ms -> [11] 161ms -> [13] 473ms -> factory:196ms building:3ms dependencies:1ms = 859ms
[15] ./~/jquery/src/selector.js 33 bytes {0} [built]
[0] 25ms -> [16] 172ms -> factory:449ms building:180ms = 826ms
[16] ./~/jquery/src/manipulation.js 15 kB {0} [built]
[0] 25ms -> factory:16ms building:156ms dependencies:443ms = 640ms
...
No errors. Nothing of any real value.
Apparently Webpack does not normalize the path separators, so we must alter the regex to accommodate Windows-style directory separators.
Here is a platform-independent regex you can use, so it can work on both *nix systems and Windows.
{ test: /jquery[\\\/]src[\\\/]selector\.js$/, loader: 'amd-define-factory-patcher-loader' }
I've also updated the blog post to use this form. If you continue to have trouble, let me know!
Full disclosure: I wrote the blog post to which this question is referring, and happened to discover this question about it today.
Not sure if you ever found the solution to this yourself however based on the comments section for the origional article:
http://alexomara.com/blog/webpack-and-jquery-include-only-the-parts-you-need/
It appears the correct regex when running on Windows is:
test: /jquery\\src\\selector\.js$/, loader: "amd-define-factory-patcher-loader"
Hope that helps!

Categories