Remove console on browser when loading react app with npm start via webpack-dev-server - javascript

So after npm build and npm run , why does my react application open with console on the screen? It was not happening when my packages were "webpack-cli": "^4.2.0" and "webpack-dev-server": "^3.11.1". Upgrading them is causing this issue. How can we fix this?
My package.json contains (devDependencies)
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^7.0.0",
"webpack": "^5.11.0",
"webpack-bundle-analyzer": "^4.3.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.3",
"webpack-manifest-plugin": "2.2.0",
"webpack-merge": "^5.7.2"
"eslint-webpack-plugin": "^2.1.0",
"html-webpack-plugin": "5.3.2",
"scripts": {
"start": "webpack serve --config config/webpack.config.js --env TARGET_ENV=development --env app=web --port 3000",
"build": "webpack --config config/webpack.config.js --env TARGET_ENV=production",
"build:staging": "webpack --config config/webpack.config.js --env TARGET_ENV=staging"
}
webpack.config.js
const { merge } = require("webpack-merge");
//const commonConfig = require("./webpack.common.js");
const paths = require("./paths");
const webpack = require("webpack");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require("eslint-webpack-plugin");
const getClientEnvironment = require("./env");
module.exports = (env) => {
const targetEnv = env.TARGET_ENV;
const mode = targetEnv === "development" ? "development" : "production";
process.env.NODE_ENV = mode;
// Source maps are resource heavy and can cause out of memory issue for large source files.
// const shouldUseSourceMap = webpackEnv === "development";
const commonConfig = {
mode: mode,
// Where webpack looks to start building the bundle
entry: {
web: paths.src + "/web.tsx",
},
// Where webpack outputs the assets and bundles
resolve: {
extensions: [".tsx", ".ts", ".js"],
fallback: {
util: require.resolve("util/"),
},
modules: ["node_modules", "./src"],
},
// Customize the webpack build process
plugins: [
new webpack.ProvidePlugin({
process: "process/browser",
}),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV is set to production
// during a production build.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(getClientEnvironment(targetEnv).stringified),
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
}),
// Removes/cleans build folders and unused assets when rebuilding
new CleanWebpackPlugin(),
// Copies files from target to destination folder
new CopyWebpackPlugin({
patterns: [
{
from: paths.public,
to: paths.build,
globOptions: {
ignore: ["**/*.html"],
},
},
{
from: paths.appPath + "/web.config",
to: paths.build,
},
],
}),
// Generates an HTML file from a template
// Generates deprecation warning: https://github.com/jantimon/html-webpack-plugin/issues/1501
new HtmlWebpackPlugin({
//favicon: paths.src + "/images/favicon.png",
template: paths.public + "/web.html", // template file
chunks: ["vendor", "web"],
filename: "web.html", // output file
inject: true,
}),
new HtmlWebpackPlugin({
template: paths.public + "/crossplatform.html", // template file
chunks: ["vendor", "crossplatform"],
filename: "crossplatform.html", // output file
inject: true,
}),
new ESLintPlugin({
// Plugin options
extensions: ["js", "jsx", "ts", "tsx"],
}),
],
// Determine how modules within the project are treated
module: {
rules: [
// JavaScript: Use Babel to transpile JavaScript files
{
test: /\.(ts|js)x?$/,
include: paths.src,
//exclude: /node_modules/,
loader: "babel-loader",
options: {
cacheDirectory: true,
// See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
// Babel sourcemaps are needed for debugging into node_modules
// code. Without the options below, debuggers like VSCode
// show incorrect code and set breakpoints on the wrong lines.
//sourceMaps: shouldUseSourceMap,
//inputSourceMap: shouldUseSourceMap,
},
},
// Images: Copy image files to build folder
{ test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: "asset/resource" },
// Fonts and SVGs: Inline files
{ test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: "asset/inline" },
],
},
};
const envConfig = require(`./webpack.${mode}.js`)({ app: env.app });
return merge(commonConfig, envConfig);
};
webpack.development.js
const webpack = require("webpack");
const paths = require("./paths");
module.exports = (args) => {
return {
// Control how source maps are generated
devtool: "cheap-module-source-map",
output: {
//path: paths.build,
publicPath: "./",
filename: "[name].js",
},
// Needed because of an issue with webpack dev server HMR with Webpack https://github.com/webpack/webpack-dev-server/issues/2758
target: "web",
// Spin up a server for quick development
devServer: {
historyApiFallback: {
index: "/" + args.app + ".html",
},
open: true,
devMiddleware: {
publicPath: "/",
},
hot: true,
// By default files from `contentBase` will not trigger a page reload.
// watchContentBase: true,
},
module: {
rules: [
// Styles: Inject CSS into the head with source maps
{
test: /\.(css)$/,
use: [
"style-loader",
{
loader: "css-loader",
//options: { sourceMap: true },
},
],
},
],
},
};
};

Related

WebPack output.library.type var is undefined

I am learning WebPack with a shortcode. In the code, we are trying to calculate the cube and square. They will suppose to store in a variable as per the following webpack.config.js.
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const isDevelopment = process.env.NODE_ENV === 'development';
const config = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
library: {
type: 'var',
name: 'testVar'
},
filename: '[name].js'
},
mode: 'production',
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css",
}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
new HtmlWebpackPlugin({
hash: true,
title: 'Video Player Play Ground',
myPageHeader: 'Sample Video Player',
template: './src/index.html',
filename: 'index.html'
})
],
module: {
rules: [
{
test: /\.s[ac]ss$/i,
exclude: /node_modules/,
use: [
// fallback to style-loader in development
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader",
],
},
{
test: /\.ts(x)?$/,
loader: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.svg$/,
use: 'file-loader'
}
]
},
resolve: {
extensions: [
'.tsx',
'.ts',
'.js',
'.scss'
]
},
optimization: {
usedExports: true,
runtimeChunk: false,
minimize: false
}
};
module.exports = config;
As shown in the above config, we store the compiled javascript in the variable with the name "testVar".
The above approach working fine when we are using the following command line code "webpack --mode production"
In the final generated javascript file we have a line which equals to
testVar = webpack_exports;
Also, testVar.start is working fine.
But the above approach is not working when we are using the following command line "webpack serve --mode production" or "webpack serve"
When we run a local server, the testVar.start is undefined. I am not sure what I am doing wrong.
Following is the code we are using in the index.html file to call the start function, which we defined in our internal javascript
window.onload = function (){
alert(testVar);
console.log(testVar);
if(testVar.start !== undefined)
{
alert(testVar.start);
console.log(testVar.start);
testVar.start(3,2);
}
else {
alert("Start Function is undefined");
}
}
Also following is the code insight from index.ts and math.ts.
import {cube, square} from './math';
export function start(c:number, s:number) {
console.log(cube(c));
console.log(square(s));
}
export function square(x:number) {
return x * x;
}
export function cube(x:number) {
return x * x * x;
}
enter image description here
Finally, I got it working :-).
I need to add the following line in my webpack.config.js
devServer: {
injectClient: false
},
Following is the reference URL: https://github.com/webpack/webpack-dev-server/issues/2484
Don't forget to Vote it. Thanks.

Webpack bundle Node Express with hot reloading = hell

I hate to admit it, but I've been spending three long evenings trying to do - what I thought would be straightforward thing to do. I finally reached the stage where I'm fed up with it, and frankly rather frustrated because "it just won't work".
Here is what I try to achieve:
Bundle my Express server with Webpack (although my current code just renders a string in the browser, it is supposed to compile server rendered React components compiled with Babel)
Save the bundle in memory (or on disk if there is no other way)
Run webpack / dev / hot middleware to serve my Node Express app in a way that changes to the server rendered pages (which will be React components) will auto-update in the browser.
I've tried numerous combinations, tutorials that have been deprecated, npm packages that are no longer maintained and downloaded examples that just don't work.
Here is my current setup:
webpack.server.config.js:
const path = require('path');
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
module.exports = {
name: 'server',
mode: 'development',
target: 'node',
externals: nodeExternals(),
entry: [ './src/server/index' ],
output: {
path: path.resolve(__dirname, 'dist'),
// path: "/",
filename: '[name].js',
publicPath: '/assets/',
libraryTarget: 'commonjs2'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [
{
test: /.js$/,
loader: 'babel-loader',
include: path.resolve(__dirname, 'src/'),
exclude: /node_modules/,
options: {
presets:
[['#babel/preset-env', { modules: 'false' }], '#babel/preset-react'],
plugins: [
['#babel/plugin-proposal-object-rest-spread', { useBuiltIns: true }],
'#babel/plugin-proposal-class-properties'
]
}
},
{
test: /\.scss$/,
loader: 'ignore-loader'
},
{
test: /\.css$/,
loader: 'ignore-loader'
},
{
test: /\.(jpg|png|svg|gif|pdf)$/,
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
}
]
}
};
index.js:
import http from 'http';
import fs from "fs";
import express from "express";
import favicon from 'serve-favicon';
// import renderer from "./renderer";
import renderApp from './welcome';
const app = express();
app.use(favicon('./public/favicon.ico'));
app.use(express.static("public"));
if (process.env.NODE_ENV !== 'production') {
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const serverConfig = require('../../webpack.server.config');
const compiler = webpack(serverConfig);
app.use(webpackDevMiddleware(compiler, {
stats: {colors: true},
headers: { "Access-Control-Allow-Origin": "http://localhost"},
publicPath: serverConfig.output.publicPath
}));
app.use(require("webpack-hot-middleware")(compiler));
}
app.get("*", function(req, res) {
fs.readFile("./src/server/html/index.html", "utf8", function(err, data) {
const context = {};
const html = renderApp();
//const html = renderer(data, req.path, context);
res.set('content-type', 'text/html');
res.send(html);
res.end();
});
});
const PORT = process.env.PORT || 8080;
app.listen(3000);
Frankly I'm also rather confused about how this is supposed to work.
Are the following steps supposed to be executed?:
webpack webpack.server.config.js --watch
node dist/server.js // webpack output folder
Would this magically hot reload my server?
All help is welcome, or if you happened to have a working demo.
I just couldn't manage to make this work.
In the end I will also hot reload (re-render) my client bundle but I guess that will be the easy part as I've seen many, many resources about that.
Night sleep was probably needed.
I got this working (incl with React server rendered components) using StartServerPlugin.
Following setup hot reloads the Node Express server:
const path = require('path');
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const StartServerPlugin = require('start-server-webpack-plugin');
module.exports = {
name: 'server',
mode: 'development',
target: 'node',
externals: nodeExternals({
whitelist: ['webpack/hot/poll?1000']
}),
entry: [ 'webpack/hot/poll?1000', './src/server/index' ],
output: {
path: path.resolve(__dirname, 'dist'),
// path: "/",
filename: 'server.js',
publicPath: '/assets/',
libraryTarget: 'commonjs2'
},
plugins: [
new StartServerPlugin({'name': 'server.js', nodeArgs: ['--inspect']}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
"process.env": {
"BUILD_TARGET": JSON.stringify('server')
}
})
],
module: {
rules: [
{
test: /.js$/,
loader: 'babel-loader',
include: path.resolve(__dirname, 'src/'),
exclude: /node_modules/,
options: {
presets:
[['#babel/preset-env', { modules: 'false' }], '#babel/preset-react'],
plugins: [
['#babel/plugin-proposal-object-rest-spread', { useBuiltIns: true }],
'#babel/plugin-proposal-class-properties'
]
}
},
{
test: /\.scss$/,
loader: 'ignore-loader'
},
{
test: /\.css$/,
loader: 'ignore-loader'
},
{
test: /\.(jpg|png|svg|gif|pdf)$/,
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
}
]
}
};
index.js:
import http from 'http'
import app from './server'
const server = http.createServer(app)
let currentApp = app;
const PORT = process.env.PORT || 8080;
server.listen(PORT);
if (module.hot) {
module.hot.accept('./server', () => {
server.removeListener('request', currentApp);
server.on('request', app);
currentApp = app;
})
}
server.js:
import http from 'http';
import fs from "fs";
import express from "express";
import favicon from 'serve-favicon';
import renderer from "./renderer";
import renderApp from './welcome';
const app = express();
app.use(favicon('./public/favicon.ico'));
app.use(express.static("public"));
app.get("*", function(req, res) {
fs.readFile("./src/server/html/index.html", "utf8", function(err, data) {
const context = {};
//const html = renderApp();
console.log('test');
const html = renderer(data, req.path, context);
res.set('content-type', 'text/html');
res.send(html);
res.end();
});
});
export default app;
Run with:
rm -rf ./dist && webpack --config webpack.server.config.js --watch
I think anwsers here are bit too complicated. It seems that Webpack does not make this easy.
Rather than trying to cook up complicated configurations, I took the issue in my own hand and created a small devserver, that does both the webpack build and server reload upon file changes. The client also has a reload logic, so the page in both cases is auto reloaded.
hot module reload for express server and webpack client
Synopsis
devserver
const fetch = require('node-fetch')
let process
function spawnserver(){
process = require('child_process').spawn("node", ["server/server.js", "dev"])
process.stdout.on('data', (data) => {
console.error(`stdout: ${data}`)
})
process.stderr.on('data', (data) => {
console.error(`stderr: ${data}`)
})
}
function rebuildsrc(){
process = require('child_process').spawn("npm", ["run", "build"])
process.stdout.on('data', (data) => {
console.error(`stdout: ${data}`)
})
process.stderr.on('data', (data) => {
console.error(`stderr: ${data}`)
})
process.on("close", code => {
console.log("build exited with code", code)
fetch("http://localhost:3000/reloadsrc").then(response=>response.text().then(content=>console.log(content)))
})
}
spawnserver()
const watcher = require("chokidar").watch("./server")
watcher.on("ready", _=>{
watcher.on("all", _=>{
console.log("server reload")
process.kill()
spawnserver()
})
})
const srcWatcher = require("chokidar").watch("./src")
srcWatcher.on("ready", _=>{
srcWatcher.on("all", _=>{
console.log("rebuild src")
rebuildsrc()
})
})
client reload
let stamp = new Date().getTime()
let lastStamp = null
app.get('/stamp', (req, res) => {
lastStamp = new Date().getTime()
res.send(`${stamp}`)
})
app.get('/reloadsrc', (req, res) => {
stamp = new Date().getTime()
res.send(`updated stamp to ${stamp}`)
})
let welcomeMessage = "Welcome !!"
let reloadScript = IS_PROD ? ``:`
let stamp = null
let reloadStarted = false
setInterval(_=>{
fetch('/stamp').then(response=>response.text().then(content=>{
if(stamp){
if(content != stamp) setTimeout(_=>{
if(!reloadStarted){
console.log("commence reload")
setInterval(_=>{
fetch(document.location.href).then(response=>response.text().then(content=>{
if(content.match(/Welcome/)){
console.log("reloading")
document.location.reload()
}
}))
}, 1000)
reloadStarted = true
}
}, 500)
}else{
if(!reloadStarted){
stamp = content
console.log("stamp set to", stamp)
}
}
}))
}, 200)
`
app.use('/dist', express.static('dist'))
app.get('/', (req, res) => {
res.send(`
<!doctype html>
<head>
<title>Reload Express Sample App</title>
</head>
<body>
<h1>${welcomeMessage}</h1>
<script>
${reloadScript}
</script>
<script src="dist/bundle.js"></script>
</body>
</html>
`)
})
Node.js, babel and webpack have been the bane of my month. There's several components that should be included. You should have a start file called "package.json"
The contents should look like:
{
"name": "react-complete-guide",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server",
"build": "rimraf dist && webpack --config webpack.prod.config.js --progress --profile --color"
},
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^7.1.5",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-preset-env": "^1.6.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"css-loader": "^0.28.7",
"file-loader": "^1.1.5",
"html-webpack-plugin": "^2.30.1",
"postcss-loader": "^2.0.7",
"style-loader": "^0.19.0",
"url-loader": "^0.6.2",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1"
},
"dependencies": {
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-router-dom": "^4.2.2"
}
}
If you type "npm start", then the bit of code "start": "webpack-dev-server" is run. This will load a preview of the code.
To package the contents into a build you type "npm run build" and that will run the code "build": "rimraf dist && webpack --config webpack.prod.config.js --progress --profile --color". That code will run the "rimraf", which deletes the "dist" folder if it exists, the rest runs the webpack config file.
You should have two webpack files. One for hot reloads and one for packaging for the production environment. The files should be called:
"webpack.config.js" and "webpack.prod.config.js".
The contents of "webpack.config.js" look like this:
const path = require('path');
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
chunkFilename: '[id].js',
publicPath: ''
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]'
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer({
browsers: [
"> 1%",
"last 2 versions"
]
})
]
}
}
]
},
{
test: /\.(png|jpe?g|gif)$/,
loader: 'url-loader?limit=8000&name=images/[name].[ext]'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + '/src/index.html',
filename: 'index.html',
inject: 'body'
})
]
};
The contents of "webpack.prod.config.js" look like this:
const path = require('path');
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
devtool: 'cheap-module-source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist/new'),
filename: 'bundle.js',
chunkFilename: '[id].js',
publicPath: ''
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]'
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer({
browsers: [
"> 1%",
"last 2 versions"
]
})
]
}
}
]
},
{
test: /\.(png|jpe?g|gif)$/,
loader: 'url-loader?limit=8000&name=images/[name].[ext]'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + '/src/index.html',
filename: 'index.html',
inject: 'body'
}),
new webpack.optimize.UglifyJsPlugin()
]
};
You also need a file to tell babel how to act. The file is called ".babelrc" if you are using babel. The contents look like this
{
"presets": [
["env", {
"targets": {
"browsers": [
"> 1%",
"last 2 versions"
]
}
}],
"stage-2",
"react"
],
"plugins": [
"syntax-dynamic-import"
]
}
There's a lot going on in this code. I strongly recomment watching some tutorial videos on this.

Webpack watch is failing me

EDIT: It's now resolved. Got in to work this morning and thought "have you tried turning it on and off again?". So I did. Removed node_modules, reinstalled all packages - it worked. FML.
I'm upgrading to Webpack 4 and can't seem to get the watch to work.
When I run the watch script everything runs as expected the first time, but errors out during a file update.
The scripts I try:
"dev": "cross-env ENV=dev webpack --config config/bundling/webpack.config.js --mode=development",
"watch": "cross-env WATCH=true yarn run dev --watch"
(redundancies in the cross-env variables will be fixed later)
The errors I get are the following:
"WARNING in configuration
The 'mode' option has not been set, webpack will fallback to
'production' for this value. Set 'mode' option to 'development' or
'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior.
Learn more: https://webpack.js.org/concepts/mode/"
"ERROR in multi (webpack)-dev-server/client?http://localhost:8080 ./src
Module not found: Error: Can't resolve './src' in [MY PATH HERE]
# multi (webpack)-dev-server/client?http://localhost:8080 ./src main[1]"
It seems like it doesn't read my webpack.config.js or the mode variable the on watch? Also, it succeeds in building the bundle, leading me to thing this might be an issue solely with the built-in webpack-dev-server.
I've tried everything I can think of, changing the scripts, changing the syntax of the mode flag, setting mode in webpack.config.js, tried relative paths, tried absolute paths, tried different versions of webpack and webpack-dev-server, moved my config file to the project root, sacrificed a small CPU to the Gods of code - nothing works.
I've been at this for days without any progress. Any help would be appreciated.
Versions:
"webpack": "^4.27.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
Config:
require('dotenv').config()
const CopyWebpackPlugin = require('copy-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
const moduleRules = require('./module.rules')
const config = require('./editable.config')
module.exports = function() {
const isDev = !!(process.env.ENV === 'dev')
const isProd = !!(process.env.ENV === 'prod')
const doServe = !!(process.env.SERVE === 'true')
const doWatch = !!(process.env.WATCH === 'true')
const webpackConfig = {
// Set mode
mode: isProd ? 'production' : 'development',
// Entry points.
entry: config.entrypoints,
// JS output name and destination.
output: {
path: config.paths.public,
filename: config.outputs.javascript.filename
},
// External dependencies.
externals: config.externals,
// Custom resolutions.
resolve: config.resolve,
// Rules for handling filetypes.
module: {
rules: [
moduleRules.javascript,
moduleRules.sass,
moduleRules.fonts,
moduleRules.images,
]
},
// Plugins running in every build.
plugins: [
new FriendlyErrorsWebpackPlugin(),
new MiniCssExtractPlugin(config.outputs.css),
new CleanWebpackPlugin(config.paths.public, { root: config.paths.root }),
new CopyWebpackPlugin([{
context: config.paths.images,
from: {
glob: `${config.paths.images}/**/*`,
flatten: false,
dot: false
},
to: config.outputs.image.filename,
}]),
new CopyWebpackPlugin([{
context: config.paths.fonts,
from: {
glob: `${config.paths.fonts}/**/*`,
flatten: false,
dot: false
},
to: config.outputs.font.filename,
}]),
],
devtool: isDev ? config.settings.sourceMaps : false,
watch: doWatch
}
// Set BrowserSync settings if serving
if (doServe) {
// setting our default settings...
const browserSyncSettings = {
host: 'localhost',
port: 3000,
proxy: process.env.HOME,
files: [
{
match: ['../../**/*.php'],
fn: function (event, file) {
if (event === 'change') {
this.reload()
}
}
}
]
}
// ...and overwriting them with user settings
Object.assign(browserSyncSettings, config.settings.browserSync)
webpackConfig.plugins.push(new BrowserSyncPlugin(browserSyncSettings))
}
return webpackConfig;
}
Config, part 2
const path = require('path')
module.exports = {
paths: {
root: path.resolve(__dirname, '../../'),
public: path.resolve(__dirname, '../../public'),
src: path.resolve(__dirname, '../../src'),
javascript: path.resolve(__dirname, '../../src/js'),
sass: path.resolve(__dirname, '../../src/sass'),
fonts: path.resolve(__dirname, '../../src/fonts'),
images: path.resolve(__dirname, '../../src/images'),
relative: '../../',
external: /node_modules/
},
entrypoints: {
main: ['./src/js/app.js', './src/sass/style.scss']
},
outputs: {
javascript: { filename: 'js/[name].js' },
css: { filename: 'css/[name].css' },
font: { filename: 'fonts/[path][name].[ext]' },
image: { filename: 'images/[path][name].[ext]' }
},
externals: {
},
resolve: {
},
settings: {
sourceMaps: 'cheap-module-source-map',
autoprefixer: {
browsers: ['last 3 versions', '> 1%', 'ie >= 10'],
},
browserSync: {
host: 'localhost',
port: 3000
}
}
}
Bonus question: is it possible to watch without having Webpack 4 start up a new devServer?
Thanks! <3

Webpack dev server not auto-reloading

So I've setup webpack and webpack-dev-server, but webpack-dev-server does not auto-reload. If i modify a file and save it there is no change in the browser until I manually refresh.
Here is my webpack config and my script file that runs webpack-dev-server. Does anyone see anything that could be preventing auto-reload from working?
I put these together by reading through multiple tutorials, the docs, and by reading through the react-create-app generated files.
config/webpack.config.dev.js
'use strict';
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer');
const webpack = require('webpack');
const extractSass = new ExtractTextPlugin('style.css');
module.exports = {
entry : './src/index.jsx',
eslint: {configFile: './src/.eslintrc.json'},
module: {
loaders: [
{
exclude: /node_modules/,
include: ['src'],
loader: 'babel',
test : /(\.js|\.jsx)$/
},
{
exclude: /node_modules/,
include: ['src']
loader : extractSass.extract([ 'css', 'postcss', 'sass' ]),
test : /\.scss$/
}
],
preLoaders: [
{
exclude: /node_modules/,
loader : 'eslint',
query : {presets: [ 'react', 'latest' ]},
test : /(\.js|\.jsx)$/
}
]
},
output: {
filename : 'bundle.js',
path : 'dist',
publicPath: '/'
},
plugins: [
extractSass,
new HtmlWebpackPlugin({
inject : true,
template: paths.appHtml
}),
new webpack.HotModuleReplacementPlugin({multistep: true})
],
postcss: () => [
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9'
]
})
]
};
scripts/dev.js
run with $ yarn run dev
'use strict';
const WebpackDevServer = require('webpack-dev-server');
const config = require('../config/webpack.config.dev.js');
const webpack = require('webpack');
const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
clientLogLevel : 'warn',
compress : true,
contentBase : 'public',
filename : config.output.filename,
historyApiFallback: true,
hot : true,
inline : true,
lazy : false,
noInfo : true,
publicPath : '/',
quiet : true,
stats : 'errors-only',
watchOptions : {
aggregateTimeout: 300,
poll : 1000
}
});
server.listen(8080, 'localhost', () => {
console.log('Listening on port 8080');
});
According to the webpack dev server documentation you should add this entry point to the webpack configuration to support automatic refresh.
config.entry.unshift("webpack-dev-server/client?http://localhost:8080/");
jontem pointed out in his answer that my config was missing a webpack-dev-server client.
Here's the steps I took to apply his solution and also setup HMR.
config/webpack.config.dev.js
module.config = {
// ...
entry: [
// converted entry to an array
// to allow me to unshift the client later
path.resolve(__dirname, '../src/index.jsx')
],
// ...
module: {
loaders: {
// ...
{
// Use style loader instead of ExtractTextPlugin
// To allow for style injection / hot reloading css
exclude: /node_modules/,
loaders: [ 'style', 'css', 'postcss', 'sass' ],
test : /\.scss$/
},
// ...
}
}
}
scripts/dev.js
'use strict';
const WebpackDevServer = require('webpack-dev-server');
const config = require('../config/webpack.config.dev.js');
const webpack = require('webpack');
// unshift `webpack-dev-server` client
// and hot dev-server
config.entry.unshift('webpack-dev-server/client?/', 'webpack/hot/dev-server');
const compiler = webpack(config);
// ...
I had the same issue and the following configuration enabled static and the in-memory bundle auto-reloading. The key is to enable devServer.watchContentBase.
config/webpack.config.dev.js
...
module.exports = {
...
devServer: {
contentBase: ...,
publicPath: ...,
watchContentBase: true
},
...
}
package.json
{
...
"scripts": {
"develop": "webpack-dev-server --open --mode development --config config/webpack.config.dev.js",
...
}
...
}
Please add the following in your webpack config and try.
devServer: {
hot: true,
inline: true,
host: "localhost",
port: 8082,
watchOptions: {
poll: true
}
}
note: I was using webpack version ^3.11.0
I had a similar problem, fixed it by adding
watchOptions: {
poll: true
}
When I first installed the webpack starter, everything worked flawlessly, after a week of changes to webpack.config.js, it stopped working. I tinkered with various recommendations, the one that worked was watchOptions: {poll:true }
FYI I am webpack 4 with "webpack": "4.29.6", "webpack-cli": "^3.3.0", "webpack-dev-server": "3.3.1"
devServer: {
port: 3000,
contentBase: './',
watchOptions: {
poll: true
}
}
Also
if you use extract-loader, auto reload will not work
Hot Module Replacement feature
devServer: {
// ,,,
contentBase: '/your/path'
watchContentBase: true
hot: true,
},
prevents refresh your static files in web page, unless you press F5 button in browser
This third party webpack dev server documentation has the answer that I needed:
https://wohugb.gitbooks.io/webpack/content/dev_tools/webpack-dev-server.html
The relevant section reproduced below:
There is no inline: true flag in the webpack-dev-server configuration, because the webpack-dev-server module has no access to the webpack configuration. Instead the user have to add the webpack-dev-server client entry point to the webpack configuration.
To do this just add webpack-dev-server/client?http://: to (all) entry point(s). I. e. with the above configuration:
var config = require("./webpack.config.js");
config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080");
var compiler = webpack(config);
var server = new webpackDevServer(compiler, {...});
server.listen(8080);
I also had the same issue and after adding this code line my problem solved. Now auto reloading worked
devServer : {
contentBase : './',
watchOptions : {
poll: true
}
}
For anyone experiencing this with Webpack v5, you need to set target to web in your config, like so:
module.exports = {
entry: "...",
target: "web",
.....
}

How can I use webpack with express?

When I try to use webpack with a simple express server I always get TONS of errors:
express.js
'use strict';
var express = require('express');
var path = require('path');
var url = require('url');
// -------- my proxy----------------------
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.set('port', process.env.PORT || 8080);
app.use(function logErrors(err, req, res, next) {
console.error(err.stack);
next(err);
}
);
app.listen(app.get('port'), function() {
console.info('Express server started at http://localhost:' + app.get('port'));
});
I get all those errors:
Version: webpack 1.10.0
Time: 1200ms
Asset Size Chunks Chunk Names
outfile 559 kB 0 [emitted] main
chunk {0} outfile (main) 498 kB [rendered]
[0] ../app/server/express2.js 553 bytes {0} [built]
+ 125 hidden modules
WARNING in ../~/express/lib/view.js
Critical dependencies:
78:29-56 the request of a dependency is an expression
# ../~/express/lib/view.js 78:29-56
ERROR in ../~/express/lib/request.js
Module not found: Error: Cannot resolve module 'net' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/lib
# ../~/express/lib/request.js 18:11-25
ERROR in ../~/express/lib/view.js
Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/lib
# ../~/express/lib/view.js 18:9-22
ERROR in ../~/express/~/send/index.js
Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send
# ../~/express/~/send/index.js 25:9-22
ERROR in ../~/express/~/etag/index.js
Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/etag
# ../~/express/~/etag/index.js 22:12-25
ERROR in ../~/express/~/send/~/destroy/index.js
Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send/node_modules/destroy
# ../~/express/~/send/~/destroy/index.js 1:17-30
ERROR in ../~/express/~/send/~/mime/mime.js
Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send/node_modules/mime
# ../~/express/~/send/~/mime/mime.js 2:9-22
ERROR in ../~/express/~/send/~/statuses/codes.json
Module parse failed: /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send/node_modules/statuses/codes.json Line 2: Unexpected token :
You may need an appropriate loader to handle this file type.
| {
| "100": "Continue",
| "101": "Switching Protocols",
| "102": "Processing",
# ../~/express/~/send/~/statuses/index.js 2:12-35
ERROR in ../~/express/~/send/~/mime/types.json
Module parse failed: /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send/node_modules/mime/types.json Line 1: Unexpected token :
You may need an appropriate loader to handle this file type.
|
# ../~/express/~/send/~/mime/mime.js 87:12-35
ERROR in ../~/express/~/accepts/~/mime-types/~/mime-db/db.json
Module parse failed: /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/accepts/node_modules/mime-types/node_modules/mime-db/db.json Line 2: Unexpected token :
You may need an appropriate loader to handle this file type.
| {
| "application/1d-interleaved-parityfec": {
| "source": "iana"
| },
# ../~/express/~/accepts/~/mime-types/~/mime-db/index.js 11:17-37
ERROR in ../~/express/~/type-is/~/mime-types/~/mime-db/db.json
Module parse failed: /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/type-is/node_modules/mime-types/node_modules/mime-db/db.json Line 2: Unexpected token :
You may need an appropriate loader to handle this file type.
| {
| "application/1d-interleaved-parityfec": {
| "source": "iana"
| },
# ../~/express/~/type-is/~/mime-types/~/mime-db/index.js 11:17-37
and this is my config file:
var webpack = require('webpack');
module.exports = {
// Makes sure errors in console map to the correct file
// and line number
devtool: 'eval',
entry: [
'./bin/www.js'
],
output: {
path: './bin/out',
filename: 'server.js'
},
extensions: [
'',
'.jsx', '.js'
],
module: {
loaders: [
// Compile es6 to js.
{
test: /app\/.*\.js?$/,
loaders: [
'react-hot',
'babel-loader'
]
}
]
},
devtool: 'source-map'
};
What can I do, I need to use webpack on my server side as well.
I run the express.js file like so:
./node_modules/webpack/bin/webpack.js ../app/server/express.js outfile --display-chunks -c --progress -d
What I ended up doing was I used 2 different configurations, 1 for packing the server stuff together using webpack, and 1 for packing all the browser stuff together and also run webpack dev server for hot reloading.
Server webpack config aka webpack.node.config.js now looks like this:
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var nodeModules = {};
// note the path.resolve(__dirname, ...) part
// without it, eslint-import-resolver-webpack fails
// since eslint might be invoked with different cwd
fs.readdirSync(path.resolve(__dirname, 'node_modules'))
.filter(x => ['.bin'].indexOf(x) === -1)
.forEach(mod => { nodeModules[mod] = `commonjs ${mod}`; });
// es5 style alternative
// fs.readdirSync(path.resolve(__dirname, 'node_modules'))
// .filter(function(x) {
// return ['.bin'].indexOf(x) === -1;
// })
// .forEach(function(mod) {
// nodeModules[mod] = 'commonjs ' + mod;
// });
module.exports =
{
// The configuration for the server-side rendering
name: 'server',
target: 'node',
entry: './app/server/serverEntryPrototype.js',
output: {
path: './bin/',
publicPath: 'bin/',
filename: 'serverEntryPoint.js'
},
externals: nodeModules,
module: {
loaders: [
{ test: /\.js$/,
loaders: [
// 'imports?document=this',
// 'react-hot',
'babel-loader'
//,'jsx-loader'
]
},
{ test: /\.json$/, loader: 'json-loader' },
]
},
plugins: [
// new webpack.NormalModuleReplacementPlugin("^(react-bootstrap-modal)$", "^(react)$")
// new webpack.IgnorePlugin(new RegExp("^(react-bootstrap-modal)$"))
// new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
};
Browser webpack config aka webpack.browser.config.js now looks like this:
var webpack = require('webpack');
var path = require('path');
var buildPath = path.resolve(__dirname, 'assets');
var fs = require('fs');
var commonLoaders = [
{ test: /\.js$/,
loaders: [
'react-hot',
'babel-loader'
//,'jsx-loader'
]
}
];
module.exports =
{
// Makes sure errors in console map to the correct file
// and line number
name: 'browser',
devtool: 'eval',
entry: [
//'./bin/www.js',
'./app/index.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8081' // WebpackDevServer host and port
],
output: {
path: buildPath,
filename: '[name].js',
// Everything related to Webpack should go through a build path,
// localhost:3000/build. That makes proxying easier to handle
publicPath: 'http://localhost:8081/assets/'
},
extensions: [
'',
'.jsx', '.js',
'.json',
'.html',
'.css', '.styl', '.scss', '.sass'
],
module: {
loaders: [
// Compile es6 to js.
{
test: /app\/.*\.jsx?$/,
loaders: [
'react-hot',
'babel-loader'
]
},
///app\/.*\.json$/
{ test: /\.json$/, loader: 'json-loader' },
// Styles
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.s(a|c)ss$/, loader: 'style!css?localIdentName=[path][name]---[local]---[hash:base64:5]!postcss!sass' },
// Fonts
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff' },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file-loader' }
//{ test: /\.png$/, loader: 'url-loader?limit=100000' },
//{ test: /\.jpg$/, loader: 'file-loader' }
],
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
},
postcss: [
require('autoprefixer-core')
],
devtool: 'source-map'
}
;
It can be realized by specifying "node" to "target" option, since v1.10.2.
For reference: http://jlongster.com/Backend-Apps-with-Webpack--Part-I
If you want to bundle the server and the client's code at the same time, it is possible to use multiple configuration in the following manner.
// webpack.config.js
module.exports = [
{
name: 'server',
entry: './src/server/index.js',
target: 'node',
output: {
path: __dirname + '/dist/server',
filename: 'bundle.js',
},
},
{
name: 'client',
entry: './src/client/index.js',
// target: 'web', // by default
output: {
path: __dirname + '/dist/client',
filename: 'bundle.js',
},
}
];
I am just clarifying #meta2's answer because I believe it can be written in a more understandable way - although full points to him!
tl;dr - set target: 'node' in your webpack.config.js to fix the errors that get generated when using Webpack with Express.
You still get warnings like:
WARNING in ./node_modules/express/lib/view.js
81:13-25 Critical dependency: the request of a dependency is an expression
To fix those, use https://github.com/liady/webpack-node-externals. FYI - this reduces you bundle size significantly (check size before and after) and speeds up the bundling time incredibly.
Full example:
const path = require('path')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: './src/app.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
target: 'node', // THIS IS THE IMPORTANT PART
externals: [nodeExternals()],
mode: 'development'
}
Additionally, if you are working with Typescript, make sure to also include the ".js" extension in your config:
module.exports = {
entry: './src/server/index.ts',
target: 'node',
output: {
path: __dirname + '/dist/server',
filename: 'bundle.js',
},
resolve: {
modules: [
"node_modules"
],
extensions: [".ts", ".js"]
}
};
I took an easy approach that could be useful in a small or medium project. I make it so webpack would serve as the bundler for ecma script and scss, though in this aproach i dont use hot reloading.
The server configuration is the default given by express generator.
webpack.config.js
const path = require("path");
module.exports = {
entry: "./resources/index.js",
output: {
path: path.join(__dirname, "/public/dist"),
publicPath: "/public/dist",
filename: "main.js"
},
mode: "development",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
]
}
};
package.json is devDependencies
"devDependencies": {
"#babel/core": "^7.6.4",
"#babel/preset-env": "^7.6.3",
"babel-loader": "^8.0.6",
"css-loader": "^3.2.0",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9"
}
package.json is scripts
"scripts": {
"start": "node ./bin/www",
"dev": "nodemon",
"build": "webpack",
"watch": "webpack --watch"
},
Here is a simple setup to build an express+webpack app. Please pay attention to package.json file scripts part which starts simultaneously express server and webpack process.
And also please pay attention server.js file "app.use(express.static('dist'));" part. Express static should point to webpack folder which contains index.html and bundle.js
server.js file:
const express = require ("express");
const path = require ("path");
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(express.static('dist'));
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
})
const server = app.listen (process.env.PORT || 4000);
const portNumber = server.address().port;
console.log("ГОСПОДИН ПОРТ СЕИЧАС ОТКРЫТ "+ portNumber);
now package.json file:
{
"name": "firebase1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
"server": "node server.js",
"dev": "concurrently --kill-others-on-fail \"npm run build\" \"npm run server\""
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.64.0",
"webpack-cli": "^4.9.1"
},
"dependencies": {
"express": "^4.17.1"
}
}
Now, webpack.config.js file:
const path = require("path");
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
watch: true
}
And finally index.html file:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FIREBASE PROJECT OF MY LORD TOM AND JERRY</title>
</head>
<body>
<h1>Getting Started with Firebase</h1>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>

Categories

Resources