After updated the webpack devServer package of my project from "webpack-dev-server": "3.11.2" to "webpack-dev-server": "4.3.0" I'm facing this issue when I start my project:
>> npm run start
> backoffice#1.0.0 start
> webpack serve --config webpack.dev.js
[webpack-cli] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options has an unknown property 'writeToDisk'. These properties are valid:
object { allowedHosts?, bonjour?, client?, compress?, devMiddleware?, headers?, historyApiFallback?, host?, hot?, http2?, https?, ipc?, liveReload?, magicHtml?, onAfterSetupMiddleware?, onBeforeSetupMiddleware?, onListening?, open?, port?, proxy?, setupExitSignals?, static?, watchFiles?, webSocketServer? }
The changelog seems not to be updated and I've found only a couple of new options: More info here
How can I convert this "old" configuration file to the new one?
And if possible, where can I find the new configuration options?
webpack.dev.js:
const {merge} = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: path.join(__dirname, './dist'),
compress: true,
watchContentBase: true,
historyApiFallback: true,
https: false,
open: 'Firefox Developer Edition',
stats: {
colors: true,
},
port: 9002,
proxy: {
'/api': 'http://localhost:9000'
},
writeToDisk: true,
},
});
Thank you for your help
You simply use fields that are not allowed. Your dev-server should be written as such:
devServer: {
static: {
directory: path.join(__dirname, './dist')
},
compress: true,
historyApiFallback: true,
https: false,
open: true,
hot: true,
port: 9002,
proxy: {
'/api': 'http://localhost:9000'
}
devMiddleware: {
writeToDisk: true,
},
},
// ps: you don't need 'static' for ./dist . DevServer is here to compile and hot reload the js code that is attached to the "root" node. The dist folder is supposed to contain your final build.
// to use writeToDisk, you'll need to install webpack-dev-middleware
// npm install webpack-dev-middleware --save-dev
Related
I'm new to this webpack thing so I was looking through some Webpack 5 tutorials online and documentation but I don't know how to fix this issue
File Structure:
dist
node_modules
src
modules
js files
style
style.css
index.html
index.js
package.json
package-lock.json
webpack.config.js
Webpack Config:
const { appendFile } = require("fs");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'development',
entry: {
main: path.resolve(__dirname,'src/index.js'),
},
output: {
path:path.resolve(__dirname,'dist'),
filename: 'app.bundle.js',
hashFunction: 'xxhash64',
},
devtool: 'inline-source-map',
devServer: {
static: {
directory:path.resolve(__dirname,'dist'),
watch:true,
},
port: 8080,
open: true,
hot: true,
},
//loaders
module: {
rules: [
{test: /\.css$/, use:['style-loader','css-loader']}
]
},
//plugins
plugins: [new HtmlWebpackPlugin({
title: 'To Do List',
filename: 'index.html',
template: path.resolve(__dirname,"./src/index.html")
})]
}
When I run "npm run dev" my webpage opens with the HTML/CSS/JS but nothing changes (no recompiling happens) when I make a change to my code.
Also, another weird problem that occurs is that my import statements get deleted in the index.js file on save, not sure if thats related to this or just a VScode problem
You have a place to correct in your devServer.static.directory: it should be ./, not dist. Here is the set of devServer's settings, which worked out for me:
devServer: {
port: 8080,
hot: "only",
static: {
directory: path.join(__dirname, './'),
serveIndex: true,
},
},
I was struggling with HMR aswell and it is really disappointing to end up with almost nothing, except i got it working with this approach:
devServer: {
port: 8080,
hot: false,
liveReload: true,
watchFiles: ['dist/**/*'],
open: ['http://localhost:8080/html/index.html']
}
basically i switched to liveReload to achieve same result and it works now.
P.S. you don't need to use 'open' but my html is located in dist/html/index.html and i used a link to open window with that html
Info
I am trying to generate my own webpack config and have some problems getting it working.
Problem
When trying to use optimization to split files into chunks I get the a error like underneath
Error: Conflict: Multiple chunks emit assets to the same filename static/js/bundle.js (chunks main and vendors-node_modules_react-hot-loader_patch_js-node_modules_react_jsx-dev-runtime_js-node_mod-4610d2)
If I remove the optimization section it works but without chunking. I have looked to the create react app webpack.config.js to get something to reference while generating this.
As you can see they have the optimization section working with chunking in both development and production. Why do I get the conflict error when using it?
Code
Minified/simplified version of my config (runtimeChunk disabled, as it also gives the same conflict error)
webpack.config.js
module.exports = () => {
process.env.NODE_ENV = "development";
process.env.BABEL_ENV = "development";
return {
mode: "development",
entry: ["react-hot-loader/patch", "./src"],
output: {
path: undefined,
publicPath: "/",
filename: "static/js/bundle.js",
chunkFilename: "static/js/[name].chunk.js",
},
optimization: {
minimize: false,
splitChunks: {
chunks: "all",
name: false
},
// runtimeChunk: {
// name: (entrypoint) => `runtime-${entrypoint.name}`,
// },
},
resolve: {
modules: [path.join(__dirname, "src"), "node_modules"],
alias: {
"react-dom": "#hot-loader/react-dom",
},
},
module: {
rules: [
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: path.resolve(__dirname, "./src"),
exclude: /node_modules/,
use: ["babel-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: path.resolve(__dirname, "./public/index.html"),
}),
new webpack.HotModuleReplacementPlugin(),
],
devServer: {
compress: true,
hot: true,
contentBase: "./build",
historyApiFallback: true,
},
devtool: "inline-source-map",
};
};
.babelrc
{"presets": [["react-app", {"runtime": "automatic"}]]}
Got it to work had to change filename: "static/js/bundle.js" to filename: "static/js/[name].js"
output: {
path: undefined,
publicPath: "/",
filename: "static/js/[name].js",
chunkFilename: "static/js/[name].chunk.js",
}
If you are working on an ejected Create React App and you get a similar error
Multiple chunks emit assets to the same filename static/js/bundle.js
(chunks main and runtime-main)
you can just change the filename property in the output configuration from
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
to
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/[name].js',
Where the [name] placeholder is giving a different name to each output bundle instead of a fixed one.
In my case it was caused by the runtime-main.js file which I was generating with the runtimeChunk property inside optimization.
runtimeChunk: {
name: entrypoint => `runtime-${entrypoint.name}`,
},
I need to create 2 different JavaScript and CSS files, one minimized and the other one not.
I want to render the not minimized files only in Chrome, for the other browsers I want the regular minimized and compresed code.
I've tried with preset-env, changing the .babelrc file, I even tried with browserlist.
webpack.dev.js
const merge = require('webpack-merge');
const loaders = require('./webpack.loaders');
const plugins = require('./webpack.plugins');
const common = merge([{
mode: 'development',
entry: {
main: [
'./src/main/resources/js/index.js'
],
sitemap: [
'./src/main/resources/js/indexSiteMap.js'
],
error: [
'./src/main/resources/js/error/error.js'
],
icons: [
'./src/main/resources/js/fonts/google.js',
'./src/main/resources/js/fonts/features.font.js',
'./src/main/resources/js/fonts/generals.font.js'
]
},
output: {
filename: '[name].js',
chunkFilename: '[name].js'
},
devtool: 'source-map',
optimization: {
splitChunks: {
cacheGroups: {
libs: {
test: /node_modules/,
name: "libs",
chunks: "initial",
enforce: true
}
}
}
}
},
loaders.loadSass(),
loaders.loadHandlebars(),
loaders.loadReact(),
loaders.loadFileLoader(false),
loaders.loadFonts(false),
loaders.loadExpose(),
loaders.loadEslint(),
]);
module.exports = () => {
return merge([
common,
plugins.clean(),
plugins.extractCSS(false),
plugins.copy()
]);
}
.babelrc
{
"presets": ["#babel/env", "#babel/react"]
}
I get two different JavaScript files, the common.js and the modern.js
I'll load the modern -not minimized- file in chrome, otherwise I'll use the common.js file
You will need 2 different webpack configs, pass command line arguments like the below:
webpack --env.browser=chrome --open 'Google Chrome'
webpack --env.browser=other --open safari
And maintain 2 different webpack configs in webpack.chrome.js and webpack.other.js
and put this in webpack.config.js
module.exports = env => require(`./webpack.${env}.js`);
You will also need 2 different local servers or webpack-dev-server configs running in different ports like the below:
webpack.chrome.js
mode: 'production',
devServer: {
compress: true,
contentBase: path.join(__dirname, './dist'),
port: 9000,
},
webpack.other.js
mode: 'development',
devServer: {
contentBase: path.join(__dirname, './dist'),
port: 9001,
},
I have built an npm package and published it onto NPM.
When i npm install <my-package> and then import MyPackage from "#Acme/MyPackage"; into react i get the following error.
Module not found: Can't resolve #Acme/MyPackage
Is this becasue of how i have setup my sdk package. You can find the webpack config i use to build it below.
Btw this works if i import the script tag directly in the header, but how can i import it like this without specifically defining the script tag in the header?
webpack.config.js
const path = require('path');
// const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-package.min.js',
libraryTarget: 'umd',
library: 'MyPackage'
},
devtool: 'source-map',
resolve: {
extensions: ['.js'],
},
module: {
rules: [
{
test: /\.(js)$/,
use: 'babel-loader'
}
]
},
node: {
console: false,
global: true,
process: true,
__filename: 'mock',
__dirname: 'mock',
Buffer: true,
setImmediate: true,
fs: 'empty',
net: 'empty',
tls: 'empty'
// See "Other node core libraries" for additional options.
},
plugins: [
// new UglifyJSPlugin({ sourceMap: true }),
new CopyWebpackPlugin([
{ from: 'test/index.html', to: '' }
]),
],
};
It seems like the import doesn't know where to import the package from but since it's already in your node_modules folder I'm going to guess that either you don't have an index.js file or you haven't defined your main entry file for you package.
Every NPM package will look for an index.js file but if you have want to rename it you can actually define it in your package.json
{
"name": "yourpackage",
"version": "x.x.x",
"main": "another-name.min.js",
}
My project has this structure:
\root
\webpack.config.js
\public
\ index.html
\ ...
\ css
\ directives
\ views
\ dist (webpack output)
\app.js
\ index.html
\ app.js.map
\ style.css
\ style.css.map
when i use webpack-dev-server I launch it from /root and it loads the app. But, when i change a sass file or html file it does not reload. What is wrong with the webpack config?
Command to launch webpack:
$ cd root
$ webpack-dev-server
Webpack.config.js
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
const webConfig = {
entry: path.join(__dirname, 'public', 'js', 'app'),
output: {
path: path.join(__dirname, 'public', 'dist'),
filename: 'app.js'
},
resolve: {
modules: [__dirname, 'node_modules'],
extensions: ['.js'],
enforceExtension: false,
},
devtool: 'source-map',
devServer:{
contentBase: 'public/',
publicPath: 'public/'
},
module: {
loaders: [
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
loader: 'css-loader?modules,localIdentName=[name]__[local]--[hash:base64:5]!sass-loader'
}),
exclude: /node_modules/
},
{
test: /\.html$/,
loader: "raw-loader" // loaders: ['raw-loader'] is also perfectly acceptable.
}
]
},
plugins: [
new ExtractTextPlugin({filename: 'style.css', allChunks: true}),
new HtmlWebpackPlugin({
template: './public/index.html'
})
]
};
module.exports = webConfig;
https://medium.com/#rajaraodv/webpack-the-confusing-parts-58712f8fcad9
“inline” option adds “Live reloading” for the entire page. “hot” option enables “Hot Module Reloading” that tries to reload just the component that’s changed (instead of the entire page). If we pass both options, then, when the source changes, the webpack-dev-server will try to HMR first. If that doesn’t work, then it will reload the entire page.
Try adding this to your webpack.config file:
devServer:{
contentBase: 'public/',
publicPath: 'public/',
inline: true,
hot: true,
},
If you want, you can also call a script from your package.json file. Some thing like that:
...
scripts: {
"watch": "webpack-dev-server --progress --colors --hot --inline",
}
...
https://webpack.js.org/blog/2020-10-10-webpack-5-release/
With webpack 5, you will want to use the option watchFiles:
devServer: {
watchFiles: ["./public/*"], // string [string] object [object]
port: 3000,
open: true,
hot: true,
},
View the official docs about the watchFiles option.
just add the option watchContentBase: true, in your devServer config
stop the current activity and reload the script
devServer: {
contentBase: path.join(__dirname, 'public'),
port: 9000,
open:true,
liveReload: true,
watchContentBase: true,
},
if you have HtmlWebpackPlugin, try to remove it, weback-dev-server/webpack serve can pick the html file under ./public automatically.