Why won't webpack ignore my node_modules? - javascript

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

Related

Split Vue / webpack with single big bundle to chunks

My production build has a single 2 MB large js file. Lighthouse shows that a half of it was not used during a rendering. I would love to split it into smaller chunks.
Versions:
"#vue/cli-service": "^4.5.14",
"peerDependencies": {
"webpack": "^4.0.0"
}
I have already annotated the routes:
component: () => import(/* webpackChunkName: "user-chunk" */ './views/user/SignUp.vue'),
component: () => import(/* webpackChunkName: "content-chunk" */ './views/item/Blog.vue'),
component: () => import(/* webpackChunkName: "admin-chunk" */ './views/poll/CreatePoll.vue'),
vue.config.js forbids the chunks at this moment:
configureWebpack: {
devtool: 'source-map',
optimization: {
splitChunks: false,
},
I tried to modify it according Webpack doc, e.g.
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
And the result was not much helpful:
dist\js\chunk-vendors.ce439fb4.js 1528.75 KiB 419.19 KiB
dist\js\app.4d6fd109.js 604.22 KiB 114.19 KiB
I used to have over 30 chunks a year ago. There is no relevant commit in the webpack configuration so this is probably a consequence of some library upgrade.
dist\js\chunk-vendors.37407f10.js 1257.82 KiB 364.55 KiB
dist\js\app.9a0c381b.js 65.89 KiB 20.44 KiB
dist\js\chunk-73c49296.3fc6218f.js 44.71 KiB 10.08 KiB
dist\js\chunk-581504f2.0a864656.js 16.44 KiB 4.96 KiB
This is my endpoint: https://www.mezinamiridici.cz/ and sources.
How can I minify the initial load of my website so only the neccessary scripts are fetched?

Excluding node_modules from Webpack 4 bundle for web app

What I want to do:
Exclude my node_modules from being bundled by Webpack 4 (not just the babel-loader).
My current production bundle size:
Version: webpack 4.42.0
Time: 34941ms
Built at: 09/23/2020 2:05:13 PM
Asset Size Chunks Chunk Names
./public/bundle.js 4.87 MiB 0 [emitted] [big] bundle
Entrypoint bundle [big] = ./public/bundle.js
My current development bundle size:
Version: webpack 4.42.0
Time: 10780ms
Built at: 09/23/2020 1:50:15 PM
Asset Size Chunks Chunk Names
./public/bundle.js 10.4 MiB bundle [emitted] bundle
./public/bundle.js.map 11.2 MiB bundle [emitted] [dev] bundle
Entrypoint bundle = ./public/bundle.js ./public/bundle.js.map
To my knowledge, 4.87 MiB and 10.4 MiB are MASSIVE for a webpack bundle.
My current production webpack config:
'use strict'
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasurePlugin()
const TerserPlugin = require('terser-webpack-plugin')
module.exports = smp.wrap({
mode: 'production',
entry: {
'bundle': './client/index.js',
},
output: {
path: __dirname,
filename: './public/[name].js'
},
optimization: {
minimizer: [new TerserPlugin({
include: /\.js$/,
})],
minimize: true
},
context: __dirname,
devtool: 'source-map',
module: {
rules: [
{
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ['react', 'env']
}
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
}
})
What I have tried:
Using webpack-node-externals
target: 'node', // I've also tried target: 'web' as well.
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
This successfully excludes node_modules, BUT causes a breaking error in my app:
Uncaught ReferenceError: require is not defined
at Object.react (external "react":1)
at __webpack_require__ (bootstrap:19)
at Object../client/index.js (index.js:1)
at __webpack_require__ (bootstrap:19)
at bootstrap:83
at bootstrap:83
I've read into this and it seems that this webpack-node-externals package should not be used for web applications. Removing the externals prop, and toggling target between 'node' and 'web' does not exclude my node_modules successfully.
Am I doomed here? Do I simply have a huge application and should not expect to get the bundle size down any further from 4.87 MiB for production and 10.4 MiB for development? It seems extremely large based on everything I've read.

Fails to compile, when I try to use include with EJS files. (Error: Child compilation failed.)

I already made this a github issue, but I am suspecting there might be something trivial, that I just don't know about.
I would really appreciate some input to help me with the debuging.
Demo:
https://github.com/andrasna/html-ejs-webpack-config-issue-demo
index.ejs
<% const title = 'Hello' %>
<%- include('partial') -%>
<h1><%= `${title} World` %></h1>
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.ejs',
})
]
}
Expected behaviour
I am trying to include one EJS file into another, as per documentation:
https://ejs.co/#docs
<%- include('header'); -%>
<h1>
Title
</h1>
<p>
My page
</p>
<%- include('footer'); -%>
What I would expect, is for the HTML within partial.ejs to be included in the index.ejs file.
Current behaviour
I get "Error: Child compilation failed" (see full error message below).
However, EJS gets compiled if I remove the line with the include in index.ejs. Which is why I think the problem is specific to includes.
Any ideas?
Error message
> npm start
> html-ejs-webpack-config-issue-demo#1.0.0 start /Users/user/Dev/html-ejs-webpack-config--issue-demo
> webpack-dev-server --mode development
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /Users/user/Dev/html-ejs-webpack-config--issue-demo
✖ 「wdm」: Hash: f9f8666f87ab7acd22cd
Version: webpack 4.41.2
Time: 595ms
Built at: 19/10/2019 15:34:18
Asset Size Chunks Chunk Names
index.html 1.72 KiB [emitted]
main.js 360 KiB main [emitted] main
Entrypoint main = main.js
[0] multi (webpack)-dev-server/client?http://localhost:8080 ./src 40 bytes {main} [built]
[./node_modules/ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/ansi-regex/index.js] 135 bytes {main} [built]
[./node_modules/html-entities/index.js] 231 bytes {main} [built]
[./node_modules/loglevel/lib/loglevel.js] 7.68 KiB {main} [built]
[./node_modules/strip-ansi/index.js] 161 bytes {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost:8080] (webpack)-dev-server/client?http://localhost:8080 4.29 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.51 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js] (webpack)-dev-server/client/socket.js 1.53 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/createSocketUrl.js] (webpack)-dev-server/client/utils/createSocketUrl.js 2.89 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/log.js] (webpack)-dev-server/client/utils/log.js 964 bytes {main} [built]
[./node_modules/webpack-dev-server/client/utils/reloadApp.js] (webpack)-dev-server/client/utils/reloadApp.js 1.59 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/sendMessage.js] (webpack)-dev-server/client/utils/sendMessage.js 402 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./src/index.js] 0 bytes {main} [built]
+ 18 hidden modules
ERROR in Error: Child compilation failed:
Module build failed (from ./node_modules/html-webpack-plugin/lib/loader.js):
SyntaxError: Unexpected token )
- Function
- lodash.js:14870
[html-ejs-webpack-config--issue-demo]/[lodash]/lodash.js:14870:16
- lodash.js:473 apply
[html-ejs-webpack-config--issue-demo]/[lodash]/lodash.js:473:27
- lodash.js:15254
[html-ejs-webpack-config--issue-demo]/[lodash]/lodash.js:15254:16
- lodash.js:475 apply
[html-ejs-webpack-config--issue-demo]/[lodash]/lodash.js:475:27
- lodash.js:6563
[html-ejs-webpack-config--issue-demo]/[lodash]/lodash.js:6563:16
- lodash.js:14869 Function.template
[html-ejs-webpack-config--issue-demo]/[lodash]/lodash.js:14869:20
- SyntaxError: Unexpected token )
- compiler.js:79 childCompiler.runAsChild
[html-ejs-webpack-config--issue-demo]/[html-webpack-plugin]/lib/compiler.js:79:16
- Compiler.js:343 compile
[html-ejs-webpack-config--issue-demo]/[webpack]/lib/Compiler.js:343:11
- Compiler.js:681 hooks.afterCompile.callAsync.err
[html-ejs-webpack-config--issue-demo]/[webpack]/lib/Compiler.js:681:15
- Hook.js:154 AsyncSeriesHook.lazyCompileHook
[html-ejs-webpack-config--issue-demo]/[tapable]/lib/Hook.js:154:20
- Compiler.js:678 compilation.seal.err
[html-ejs-webpack-config--issue-demo]/[webpack]/lib/Compiler.js:678:31
- Hook.js:154 AsyncSeriesHook.lazyCompileHook
[html-ejs-webpack-config--issue-demo]/[tapable]/lib/Hook.js:154:20
- Compilation.js:1423 hooks.optimizeAssets.callAsync.err
[html-ejs-webpack-config--issue-demo]/[webpack]/lib/Compilation.js:1423:35
Child html-webpack-plugin for "index.html":
1 asset
Entrypoint undefined = index.html
[./node_modules/html-webpack-plugin/lib/loader.js!./index.ejs] 922 bytes {0} [built] [failed] [1 error]
ERROR in ./index.ejs (./node_modules/html-webpack-plugin/lib/loader.js!./index.ejs)
Module build failed (from ./node_modules/html-webpack-plugin/lib/loader.js):
SyntaxError: Unexpected token )
at Function (<anonymous>)
at /Users/user/Dev/html-ejs-webpack-config--issue-demo/node_modules/lodash/lodash.js:14870:16
at apply (/Users/user/Dev/html-ejs-webpack-config--issue-demo/node_modules/lodash/lodash.js:473:27)
at /Users/user/Dev/html-ejs-webpack-config--issue-demo/node_modules/lodash/lodash.js:15254:16
at apply (/Users/user/Dev/html-ejs-webpack-config--issue-demo/node_modules/lodash/lodash.js:475:27)
at /Users/user/Dev/html-ejs-webpack-config--issue-demo/node_modules/lodash/lodash.js:6563:16
at Function.template (/Users/user/Dev/html-ejs-webpack-config--issue-demo/node_modules/lodash/lodash.js:14869:20)
at Object.module.exports (/Users/user/Dev/html-ejs-webpack-config--issue-demo/node_modules/html-webpack-plugin/lib/loader.js:28:22)
ℹ 「wdm」: Failed to compile.
use the ejs-compiled-loader with the HtmlWebpackPlugin
npm install --save-dev ejs-compiled-loader
change webpack.config.js to:
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '!!ejs-compiled-loader!index.ejs', //Here is the Loader plugged in
})
]
}
(as described here)
Then alter your template to valid EJS. HtmlWebpackPlugin says: "By default (if you don't specify any loader in any way) a fallback lodash loader kicks in." It renders the template with lodash as a minimalistic loader. This is why your errors come from lodash.js .
index.ejs:
<% title = 'Hello' %>
<%- include partial -%>
<h1><%= title%> World</h1>
Then npm start and your fresh compiled "Lorem Ipsum ...Hello World" will be served on your localhost.
Or npx webpack --mode=development to get your 'dist/index.html' to enjoy the source :)
Issue with your use-case is your webpack file you are not using ejs compiler.
I made some changes and refactor some bad practice you had.
final code you can find below:
https://gitlab.com/akhileshcoder/ejs-webpack-starter
Now your webpack.config looks like below (as a task/project handler for client)
module.exports = {
devServer: {
inline:true,
port: 8080
},
entry: './src/index.js',
output: {
path: __dirname + '/public/dist',
filename: 'bundle.js',
publicPath: '/public/dist',
library: 'bundle',
libraryTarget: 'var'
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
]
}
]
}
};
and ejb gets render on express as below:
app.set('views', path.join(__dirname, '../views'));
app.set('view engine', 'ejs');
app.get('/', function(req, res, next) {
res.render('index', {title: 'Hello World'});
});

Split vendor libraries into multiple chunks with webpack

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

Webpack production build does not load anything

I've been working on an app using React and Webpack for a little while. My development environment works fine, and everything loads properly using webpack-dev-server.
I decided to run a production build of the application to see what the end-product might look like size-wise and observe the general output of the webpack product build.
It turns out that running webpack -p, while it does produce output (more on that in a minute), does not load anything at all when I hit the site in a browser.. A quick check of the output tells me that none of my component code is making it into the webpack -p build.
The images and HTML copy over as they exist in my src (dev) folder, however my JS bundle output is extremely small - the file (main.js) is only 246 bytes.
Here is the output from running webpack -p
$ npm run build
> project#0.1.0 build /Users/me/Development/project
> NODE_ENV=production webpack -p --bail --progress --config webpack.config.babel.js
Hash: 9e5f6974ce21c920a375
Version: webpack 1.12.10
Time: 2003ms
Asset Size Chunks Chunk Names
index.html 1.45 kB [emitted]
images/edit.svg 524 bytes [emitted]
images/search.svg 1.19 kB [emitted]
main.js 246 bytes 0, 1 [emitted] javascript, html
+ 219 hidden modules
When I run the development version of the project, the output is markedly different... I know that the dev server dependencies are in there, and the code is not minified.. And, most importantly - everything works as expected when running the dev server.
$ npm start
> project#0.1.0 start /Users/me/Development/project
> webpack-dev-server --hot --display-modules --config webpack.config.babel.js
http://localhost:3333/
webpack result is served from /
content is served from /Users/me/Development/project/dist
Hash: 1b34ed58f9e323966ada
Version: webpack 1.12.10
Time: 2745ms
Asset Size Chunks Chunk Names
index.html 1.45 kB [emitted]
images/edit.svg 524 bytes [emitted]
images/search.svg 1.19 kB [emitted]
main.js 1.54 MB 0, 1 [emitted] html, javascript
Here's my webpack.config.babel.js file:
import webpack from 'webpack';
import path from 'path';
import ModernizrWebpackPlugin from 'modernizr-webpack-plugin';
import modernizrConfig from './modernizr.config';
const appDir = path.resolve(__dirname, './src');
const distDir = path.resolve(__dirname, './dist');
const nodeModulesDir = path.resolve(__dirname, './node_modules');
const excludeDirs = /(node_modules|bower_components)/;
module.exports = {
entry: {
javascript: appDir + '/main.js',
html: appDir + '/index.html'
},
output: {
path: distDir,
filename: 'main.js',
},
devServer: {
contentBase: distDir,
inline: true,
port: 3333
},
resolve: {
extensions: ['', '.js', '.es6'],
modulesDirectories: [
'node_modules',
'./src'
]
},
plugins: [
// new webpack.optimize.CommonsChunkPlugin('common.js'),
// new ModernizrWebpackPlugin(modernizrConfig),
],
sassLoader: {
sourceMap: false,
includePaths: [
appDir,
nodeModulesDir,
nodeModulesDir + '/breakpoint-sass/stylesheets/',
nodeModulesDir + '/susy/sass'
]
},
module: {
loaders: [
{ // js/jsx
test: /\.js?$/,
exclude: excludeDirs,
loader: 'babel',
query: {
cacheDirectory: true,
presets: [
'es2015', 'react'
]
}
},
{ // html
test: /\.html$/,
exclude: excludeDirs,
loader: 'file?name=[name].[ext]'
},
{ // images
test: /\.(gif|png|jpg|jpeg|svg)$/,
exclude: excludeDirs,
loader: 'file?name=images/[name].[ext]'
},
{ // sass
test: /\.scss$/,
exclude: excludeDirs,
loader: 'style!css!sass'
}
]
}
}
I don't think I've got a particularly complex, or uncommon setup, and I've tried changing everything from es2015/es6 to commonJS already as well, with the same result.
I'm at a loss as to what the issue could possibly be here; hoping that someone can point out some obvious error I've got, or perhaps suggest config updates/changes that could resolve this problem.
Thanks for taking the time to read everything!
As I mentioned in my comment, I've been using webpack successfully for months now, and I've never come across using an HTML file as an entry point.
Usually you'll use Webpack to package up javascript, css, and sometimes images (ie: "assets") to be used by an html file. Serving that HTML file is outside the realm of Webpack's responsibility.
I would suggest using Webpack to generate only the final javascript bundle, then using some other method (ie: express, or some other web server) to serve that file and the html that consumes it.

Categories