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
Related
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
Im trying to get some server side rendering to work for my react project with yarn, webpack and babel. When I type in yarn watch in the terminal the program compiles correctly and then the localhost window appears, It says "Can not get /". This is because I need a output(I think), but I am unsure as in how to create one correctly.
here below is the code inside my webpack.config.js file:
const path = require("path");
module.exports = {
devServer: {
contentBase: path.resolve(__dirname, "./src" ),
historyApiFallback: true,
writeToDisk: true,
},
entry: path.resolve(__dirname, "./src/index.js" ),
module: {
rules: [
{
test: /\.js$/, exclude: /node_modules/, use:"babel-loader"
},
{
test: /\.css$/i,
use: ["css-loader"]
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
use: ["url-loader"]
},
]
},
output: {
path: __dirname + '/dist',
filename: "bundle.js"
},
};
The Bundle.js filename in the output was made in the public folder inside the index.html.
<script src="bundle.js"></script>
Sorry if this made no sense but I dont understand how this does not work correctly.
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,
},
Recently I came across the same issue as the post "historyApiFallback doesn't work in Webpack dev server".
I will first quote the accepted answer in that post.
Answer:
I meet the same question today. let config in webpack.config.js:
output.publicPath be equal to devServer.historyApiFallback.index and
point out html file route.my webpack-dev-server version is 1.10.1 and work well. http://webpack.github.io/docs/webpack-dev-server.html#the-historyapifallback-option doesn't work, you must point out html file route.
module.exports = {
entry: "./src/app/index.js",
output: {
path: path.resolve(__dirname, 'build'),
publicPath: 'build',
filename: 'bundle-main.js'
},
devServer: {
historyApiFallback:{
index:'build/index.html'
},
},
};
I tried to use this answer to fix the problem(set output.publicPath: 'dist' and devServer.historyApiFallback:{index:'dist/index.html'})
but somehow it didn't work.
After some search I found this page. According to the description in the page:
This section is for everyone who ran into this problem in development
using webpack-dev-server.. Just as above, what we need to do it tell
Webpack Dev Sever to redirect all server requests to /index.html.
There are just two properties in your webpack config you need to set
to do this, publicPath and historyApiFallback.
module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js',
publicPath: '/'
},
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ]}
]
},
devServer: {
historyApiFallback: true,
},
plugins: [
new HtmlWebpackPlugin({
template: 'app/index.html'
})
]
};
According to the config I modified my devServer.historyApiFallback to be true, and output.publicPath to be /.
My webpack config:
const webpack = require("webpack")
const path = require("path")
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: "development",
entry: {
app: "./src/base/index.js"
},
output: {
filename: "[name].bundle.js",
publicPath: '/',
path: path.resolve(__dirname, "dist")
},
devtool: 'inline-source-map',
devServer: {
hot: true,
port: 3000,
historyApiFallback: true
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(scss|css)$/,
use: [
"style-loader",
"css-loader",
"sass-loader"
]
},
{
test: /\.(pdf|jpg|png|gif|svg|ico)$/,
use: [
{
loader: 'url-loader'
},
]
},
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/base/index.html'
}),
new webpack.HotModuleReplacementPlugin()
],
}
Everything seemed working now.
But I have the puzzle that I don't know why it's working.
To be specific
devServer.historyApiFallback: true is clear according to webpack doc, so I'm not doubt about that part.
output.publicPath:/ is pretty vague for me though.
Question:
If I tried to use something like output.publicPath:/public, it
will not work. So why I must use output.publicPath:/ here?
How output.publicPath:/ can tell webpack-devserver to find the
right place and server the right index.html(which is generated by the
devserver I believe)?
Sry if it's a bit tedious. I just want to provide some detail.
But I have the puzzle that I don't know why it's working.
Setting 1
In webpack.config.js the setting
output: {
...
publicPath: '/static1/',
},
tells webpack to embed '/static1/' into the bundle's path in the generated .html file:
<script src="/static1/<name>.bundle.js" type="text/javascript"></script>
You can open the generated .html file(s) on disk and see the above tag with '/static1/' prepended to the bundle.
Setting 2
This setting:
devServer: {
publicPath: '/static/', // different from 'static1' we used above
tells webpack-dev-server to create a route handler for the path /static and serve resourses e.g. /static/<name>.bundle.js. The webpack-dev-server is based on Express which uses route handlers e.g. app.use(/mypath, ...); to serve requests.
If now you point a browser to localhost:8080, you will see blank screen. Righ-click on it to see Page Source. You will see the above <script>tag that makes the browser issue GET request for the bundle using the path /static1/xxx that doesn't work because you didn't tell webpack-dev-server to create a route handler for this path. Now type in the browser navigation bar
http://localhost:8080/static/<name>.bundle.js and you will see the internals of your bundle.
Eliminate the discrepancy between static1 and static and the page will render. In your case it works because one setting is set explicitly to '/' and the second one defaults to the same value.
Setting 3
historyApiFallback has a more narrow scope than other two settings because it is used with SPAs only. During the initial rendering a user sees the landing page of the SPA e.g. /mysample.html. This is the file with our <script> tag shown above. It should be used without any path like /static prepended to it:
historyApiFallback: {
...
index: mysample.html,
because Setting1 and Setting2 apply to bundles, not to bundle-containing .html pages.
Faced the same problem, it was succeeded to solve, having specified a route, instead of a path to index.html
devServer: {
publicPath: `/myApp`,
historyApiFallback: {
rewrites: [
{ from: /\/myApp/, to: `/myApp` }
]
}
}
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.