I am having trouble with webpacks code splitting functionality. I am trying to have 2 named chunks for two routes in my application which are not often visited. mysite.com/settings and mysite.com/access.
here is my webpack.config.coffee
module.exports =
contentBase: "#{__dirname}/src/"
cache: true
entry:
app: './src/coffee/app'
head: './src/coffee/head'
output:
path: path.join(__dirname, 'build')
publicPath: '/'
filename: '[name].js'
chunkFilename: '[name]-[chunkhash].js'
plugins: []
And here is my router.coffee
access: (slug) ->
_this = #
require.ensure ['../view/page/access-page.coffee'], (require) ->
AccessPage = require '../view/page/access-page.coffee'
accessPage = AccessPage.getInstance()
accessPage.render() unless accessPage.isRendered
_this.showPage accessPage
, 'access'
settings: (slug) ->
_this = #
require.ensure ['../view/page/settings-page.coffee'], (require) ->
SettingsPage = require '../view/page/settings-page.coffee'
settingsPage = SettingsPage.getInstance()
settingsPage.render() unless settingsPage.isRendered
_this.showPage settingsPage
, 'settings'
I am not using the webpack dev-server, instead I am watching simply by using the following cmd-line tool
webpack -d --progress --colors --watch
The problem is that it ignores the names when requiring the files, as you can see the format is '[name]-[hash].js' it generates files with the correct format e.g. settings-2j3nekj2n3ejkn2.js but during development, when I attempt to load the page, the browser complains that '-2j3nekj2n3ejkn2.js' cannot be found, somehow the mapping of the files, ignores the names. If I leave out the names, then it works.
So the question is how can I setup mulitple named chunks correctly. Thanks in advance.
Note I have checked out their examples in the docs at https://github.com/webpack/docs/wiki/code-splitting
and I have followed their optimization docs aswell at
https://github.com/webpack/docs/wiki/optimization
But I am stuck
Well the simple answer is - [name= is not supported in chunkName.
The awesome guys at Webpack have actually heard my cries and implemented it
Here is the commit
https://github.com/webpack/webpack/commit/03c87c11a4219ae6ec6bfe87e570a0dacceac859
As a result of the following issue I made
https://github.com/webpack/webpack/issues/358
It is already available as of Beta ^1.3.2
Related
The app is created with the default template for Kotlin React apps:
uses KTS-based Gradle build scripts;
Kotlin JS plugin 1.6.10;
Kotlin wrappers for React 17.0.2.
When using ./gradlew browserProductionWebpack without any additional tweaks, it generates a build/distributions directory with:
all resources (without any modifications);
index.html (without any modifications);
Kotlin sources compiled into one minified .js file.
What I want is to:
add some hash to the generated .js file;
minify the index.html file and refer the hashed .js file in it;
minify all resources (.json localization files).
Please prompt me some possible direction to do it. Looking to webpack configuration by adding corresponding scripts into webpack.config.d, but no luck yet: tried adding required dependencies into build.gradle.kts, i.e.:
implementation(devNpm("terser-webpack-plugin", "5.3.1"))
implementation(devNpm("html-webpack-plugin", "5.5.0"))
and describing webpack scripts:
const TerserPlugin = require("terser-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new TerserPlugin(),
new HtmlWebpackPlugin({
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
removeComments: true,
},
}),
],
}
}
Any hint will be appreciated.
A couple of things to put into consideration first.
If some flexible bundling configuration is needed, most likely it won't be possible to use Kotlin-wrapped (Gradle) solutions. After checking the org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig it turns out that there is only a limited set of things can be configured with it.
JS-based webpack configs require a little bit of reverse engineering to find out what is generated from the Kotlin/Gradle side and how to extend it.
For simple configurations (IMHO) there is almost no need in tweaking bundling options while using the Kotlin JS plugin.
Let's start from initial webpack configs. In my case (see the short environment description in the question above) they appear in ./build/js/packages/<project-name>/webpack.config.js. These original configs will also include all contents from JS files we create inside the ./webpack.config.d folder.
Some webpack configurations require external JS dependencies. We need to declare them in the dependencies block of build.gradle.kts. In my case they are represented with:
// Bundling.
implementation(devNpm("html-webpack-plugin", "5.5.0"))
implementation(devNpm("uglifyjs-webpack-plugin", "2.2.0"))
implementation(devNpm("terser-webpack-plugin", "5.3.1"))
implementation(devNpm("copy-webpack-plugin", "9.1.0" )) // newer versions don't work correctly with npm and Yarn
implementation(devNpm("node-json-minify", "3.0.0"))
I also dropped all commonWebpackConfigs from build.gradle.kts as they are going to be performed manually on the JS level.
All webpack JS configs (inside the ./webpack.config.d folder) are divided into 3 files:
common.js (dev server configuration for both dev and production builds):
// All route paths should fallback to the index page to make SPA's routes processed correctly.
const devServer = config.devServer = config.devServer || {};
devServer.historyApiFallback = true;
development.js:
// All configs inside of this file will be enabled only in the development mode.
// To check the outputs of this config, see ../build/processedResources/js/main
if (config.mode == "development") {
const HtmlWebpackPlugin = require("html-webpack-plugin");
// Pointing to the template to be used as a base and injecting the JS sources path into.
config.plugins.push(new HtmlWebpackPlugin({ template: "./kotlin/index.html" }));
}
and production.js:
// All configs inside of this file will be enabled only in the production mode.
// The result webpack configurations file will be generated inside ../build/js/packages/<project-name>
// To check the outputs of this config, see ../build/distributions
if (config.mode == "production") {
const HtmlWebpackPlugin = require("html-webpack-plugin"),
UglifyJsWebpackPlugin = require("uglifyjs-webpack-plugin"),
TerserWebpackPlugin = require("terser-webpack-plugin"),
CopyWebpackPlugin = require("copy-webpack-plugin"),
NodeJsonMinify = require("node-json-minify");
// Where to output and how to name JS sources.
// Using hashes for correct caching.
// The index.html will be updated correspondingly to refer the compiled JS sources.
config.output.filename = "js/[name].[contenthash].js";
// Making sure optimization and minimizer configs exist, or accessing its properties can crash otherwise.
config.optimization = config.optimization || {};
const minimizer = config.optimization.minimizer = config.optimization.minimizer || [];
// Minifying HTML.
minimizer.push(new HtmlWebpackPlugin({
template: "./kotlin/index.html",
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
removeComments: true,
},
}));
// Minifying and obfuscating JS.
minimizer.push(new UglifyJsWebpackPlugin({
parallel: true, // speeds up the compilation
sourceMap: false, // help to match obfuscated functions with their origins, not needed for now
uglifyOptions: {
compress: {
drop_console: true, // removing console calls
}
}
}));
// Additional JS minification.
minimizer.push(new TerserWebpackPlugin({
extractComments: true // excluding all comments (mostly licence-related ones) into a separate file
}));
// Minifying JSON locales.
config.plugins.push(new CopyWebpackPlugin({
patterns: [
{
context: "./kotlin",
from: "./locales/**/*.json",
to: "[path][name][ext]",
transform: content => NodeJsonMinify(content.toString())
}
]
}));
}
I use styled components, so no CSS configs are provided. In other things these configs do almost the same minification as being done out-of-the-box without any additional configs. The differences are:
JS sources use a hash in their name: it is referenced correctly from the index page HTML template;
HTML template is minified;
locales (just simple JSON files) are minified.
It can look like an overhead slightly because as mentioned in the beginning, it does almost the same with minimal differences from the out-of-the-box configs. But as advantage we're getting more flexible configs which can be tweaked easier further.
With Webpack Module Federation, how do I retain development filenames when building as production?
Currently, it's changing them all to numbers like 3279.js instead of something like src_applications_myApp_jsx.js.
Parts of the Webpack config:
const { dependencies } = require('../package.json');
output: {
chunkFilename: 'vendor/[name].js',
filename: '[name]/app.js',
},
new webpack.container.ModuleFederationPlugin({
shared: dependencies,
}),
The issue is the chunkFilename. Changing it to 'vendor/[id].js' doesn't change anything either.
Webpack's docs say the [name] property will only work if the chunk has a name. So I guess, why is a name not set?
for chunks you can just use
webpackConfig.optimization.chunkIds='named'
It'll keep your chunk names readable, see link for further docu
https://webpack.js.org/configuration/optimization/#optimizationchunkids
I'm a bit lost and need some help with VueJs. I am using Vue CLI3 and have created a new Vue project where eveything is working, no errors in the console etc. However, after running the build task, the copy in my dist folder shows as a blank page. I have learnt that this is to do with needing to update the assetsPublicPath: and remove the '/' forwards slash. To do this I have been told you have to update the config file index.js but there is no such file in my proect? I have also been told there is a config folder, but there isnt?
Therefore how do I update the following
from assetsPublicPath: '/',
to assetsPublicPath: '',
Take a look at the documentation. If you don't have the vue.config.js just create it. I would look something like this:
// vue.config.js
module.exports = {
// Any of the config options will come here. Everything you'll need is in the docs
publicPath: ''
}
Only create a vue.config.js in your project and use inside .File is automatic loaded by vue cli serve. After publish your hosting or server file will must work it.
module.exports = {
css: {
extract: true
},
publicPath: process.env.NODE_ENV === "production" ? "" : "",
outputDir: "dist"
};
I have to use Webpack for one of my projects to build front-end bundles for js, css and other static assets. It does the job well, but in my early stages of the project I've got only some css and static images and no js files yet. Here is my full webpack.config.js
const Webpack = require("webpack");
const Glob = require("glob");
const path = require("path");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const configurator = {
entries: function(){
var entries = {
application: [
'./assets/dummy.js',
],
}
return entries
},
plugins() {
var plugins = [
new CopyWebpackPlugin([{from: "./assets",to: ""}], {copyUnmodified: true,ignore: ["css/**", "js/**", "**.js"] }),
];
return plugins
},
moduleOptions: function() {
return {
rules: [
]
}
},
buildConfig: function(){
const env = process.env.NODE_ENV || "development";
var config = {
mode: env,
entry: configurator.entries(),
output: {filename: "[name].[hash].js", path: `${__dirname}/public/assets`},
plugins: configurator.plugins(),
module: configurator.moduleOptions()
}
return config
}
}
module.exports = configurator.buildConfig()
Practically what it does for me is copying assets to public dir. I don't have any javascripts yet, but they will be in the future. So, I tried commenting entry, setting it to null or empty string with no luck. It seems Webpack needs to process js files so badly. My current solution is creating an empty dummy.js file and feeding it to Webpack. Annoyingly it generates some 3.3kb application.afff4a3748b8d5d33a3a.js file with some boilerplate js code, despite that my source js file is totally empty.
I understand that this is an edge use case for Webpack and Webpack was primarily created for processing javascript, but I bet many people still use it not just for bundling javascripts. So, my question, is there a better, more elegant way to skip bundling js files in Webpack?
p.s.
I think, I've found a related question without an answer here How to make WebPack copy a library instead of bundling?
p.s.#2
The suggested duplicate question has an accepted answer with an invalid Webpack config Invalid configuration object., so, I can't use it to solve my issue.
Moreover, the answer reads
webpack will create a dummy javascript file
and I'm specifically asking how to avoid creating unnecessary files.
I'm using Webpack with CommonChunksPlugin .
My problem is with lazy loaded modules.
When I load lazy modules ( 0.js and 1.js in image) , Where each uses the Http Module , it seems that Http is embedded/repeated in EACH module :
The entries in my file are :
entry: {
bundle: aot ? "./main.aot.ts" : "./main.ts",
vendor: "./vendor",
},
With CommonsChunkPlugin configured as :
new webpack.optimize.CommonsChunkPlugin({
name: ["vendor"],
}),
— I get this result where you can see multiple http.js both in bundle & 1.js& 0.js.
With CommonsChunkPlugin configured with async ( as written in here) :
new webpack.optimize.CommonsChunkPlugin({
async: true,
children: true,
}),
— I get this result where you can see tha 0.js and 1.js are OK but the bundle.js now contains dups as vendor(?!?!)
Question:
I've read the docs But as you can see , I'm trying to do something without success.
How can I fix the config so that common chunks will be extracted and not be repeated ?
webpack.config
Was having the same issue as you are/were facing.
In my case, I've removed the name parameter from the configuration and set async to true and children to true as well.
Also, make sure that the CommonChunksPlugin is the last plugin in the array of plugins.