I'm using react with webpack. My app worked well before using webpack-dev-server. Only the home page works now, the others return "404 not found". Maybe there's a problem in webpack.config.js ?
var webpack = require("webpack");
var path = require("path");
var BUILD_DIR = path.resolve(__dirname, "public");
var APP_DIR = path.resolve(__dirname, "app");
var config = {
entry: [
"webpack/hot/only-dev-server",
APP_DIR + "/main.js",
"webpack-dev-server/client?localhost:8080"
],
output: {
path: BUILD_DIR + "/dist",
filename: "bundle.js",
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [...],
},
devServer: {
noInfo: true,
hot: true,
inline: true
},
}
module.exports = config;
And my script in package.json:
"start": "webpack --watch & webpack-dev-server --content-base public"
Webpack generates well bundle file. So i think the webpack-dev-server is the one who causes this problem.
Thank you !
I've found the answer. For someone who has the same problem, we need to add "historyApiFallback: true" to devServerConfig:
devServer: {
noInfo: true,
hot: true,
inline: true,
historyApiFallback: true
},
can you change your npm script
"start": "webpack --watch & webpack-dev-server --content-base public"
to
"start": "webpack --watch & webpack-dev-server --content-base public/"
and see what happens? Otherwise I will comeback and assist you.
Related
Let's say I have 2 files which are .env.development and .env.production.
In my package.json, since the mode is development, it should access .env.development for the variables.
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js"
webpack.config.js
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const Dotenv = require("dotenv-webpack");
module.exports = {
mode: "development",
entry: path.resolve(__dirname, "./src/index.jsx"),
devtool: "source-map",
output: {
path: path.join(__dirname, "/dist"),
filename: "bundle.js",
},
devServer: {
port: 3000,
static: true,
historyApiFallback: true,
open: true,
},
resolve: {...},
module: {...},
plugins: [
new Dotenv(),
new HtmlWebpackPlugin({
template: "public/index.html",
filename: "index.html",
favicon: "public/favicon.ico",
}),
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
}),
new webpack.ProvidePlugin({
process: "process/browser",
}),
],
};
So that in the frontend, when I use process.env, it will access the variable in .env.development.
Is there any way to do it?
You can set the system environment variable NODE_ENV at the beginning of the npm script. Use this environment variable to control the built environment.
E.g.
package.json:
"scripts": {
"build:dev": "webpack",
"build": "NODE_ENV=production webpack",
"dev": "webpack serve"
}
webpack.config.js:
const path = require("path");
const Dotenv = require("dotenv-webpack");
const mode =
process.env.NODE_ENV === "production" ? "production" : "development";
console.log("mode: ", mode);
module.exports = {
mode,
entry: path.resolve(__dirname, "./src/index.jsx"),
devtool: "source-map",
output: {
path: path.join(__dirname, "./dist"),
clean: true,
},
devServer: {
port: 3000,
static: true,
historyApiFallback: true,
open: true,
},
plugins: [
new Dotenv({
path: path.resolve(__dirname, `./.env.${mode}`),
}),
],
};
.env.development:
PWD=123456
.env.production:
PWD=a)d4125z
For development build npm run build:dev, the output of ./dist/main.js:
/******/ (() => { // webpackBootstrap
var __webpack_exports__ = {};
/*!***********************!*\
!*** ./src/index.jsx ***!
\***********************/
console.log("PWD: ", "123456");
/******/ })()
;
//# sourceMappingURL=main.js.map
For production build npm run build, the output:
console.log("PWD: ","a)d4125z");
//# sourceMappingURL=main.js.map
I am requesting help setting up the compilation and dev environment for a typescript library. The library should work when consumed by a web app framework and when consumed by a script tag. I am currently using Webpack as a dev server so I can debug and TSC to build (cjs + esm). The issue that prompted this post was having to constantly switch my API strings between http://localhost:8080 to https://production.com. What tools or changes do I need in order to build dev and prod variables into my compilation?
Here is what I'm doing so far:
package.json fragment
"main": "./lib/cjs/index.js",
"module": "./lib/esm/index.js",
"files": [
"lib/**/*",
"README.md"
],
"scripts": {
"build:esm": "tsc -p tsconfig.json --outDir lib/esm --module ES2020 --sourceMap false",
"build:cjs": "tsc -p tsconfig.json --outdir lib/cjs --module commonjs --sourceMap false",
"clean:build": "rimraf lib",
"clean:serve": "rimraf dist",
"build": "rimraf lib && npm run build:esm && npm run build:cjs",
"serve": "rimraf dist && webpack-dev-server"
}
webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const SRC = path.resolve(__dirname, 'src')
const ENTRTY = path.resolve(__dirname, 'src', 'debug.ts')
const DIST = path.resolve(__dirname, 'dist')
module.exports = {
mode: 'development',
context: SRC,
entry: ENTRTY,
output: {
path: DIST,
filename: 'index.js',
},
devtool: 'source-map',
devServer: {
contentBase: DIST,
writeToDisk: true,
host: '0.0.0.0',
port: 8080,
https: true,
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin()
],
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
include: [SRC]
}
]
}
}
My toolchain does not currently allow me to do do this:
import Axios from 'axios'
import SocketIO from 'socket.io-client'
export const axios = Axios.create({
baseURL: process.env.SERVER_HTTP_URL, //<-- can't do env-vars with tsc build
withCredentials: true
})
typescript cant not do that, but gulp can do it
const replace = require('gulp-replace');
const { src, dest } = require('gulp');
exports.default = function() {
return src(['*.js'], {base: './'})
.pipe(replace('__XXXX__', 'some variables'))
.pipe(dest('./'));
}
update:
Seem I have solved my problem creating an "hot directory" in my webpack config like that :
My webpack.config.js :
output: {
path: path.join(__dirname, "public"),
filename: "bundle.js",
publicPath: "/public/",
hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json'
}
My new tree folders :
├── hot
├── package.json
├── src
└── webpack.config.js
But I still wonder how purely create these chunks in memory ?
Any hint would be great,
Thanks
I'm trying currently to work with express hot middleware. I have set my webpack.config, server.js and package.json to work with. It works fine now but generates a lot of bundles on my root directory instead of on memory, hence saturate my root's directory. I can't figure out what is wrong.
The bundle have name like the following :
main.0d50bece383b2f7c93db.hot-update.js
They are created when there is a change on my server or more generally, configuration files it seems.
Here my webpack.js :
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const autoprefixer = require("autoprefixer");
const nodeExternals = require('webpack-node-externals');
const path=require("path");
module.exports = {
mode:"development",
entry: [
"webpack-hot-middleware/client",
"./src/client/index.js"],
output: {
path: path.join(__dirname, "public"),
filename: "bundle.js",
publicPath: "/"
},
devtool: "cheap-module-source-map",
module: {
rules: [
{
test: [/\.svg$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: "file-loader",
options: {
name: "public/media/[name].[ext]",
publicPath: url => url.replace(/public/, "")
}
},
{
test: /js$/,
exclude: /(node_modules)/,
loaders: "babel-loader",
}
]
},
plugins: [
new ExtractTextPlugin({
filename: "css/[name].css"
}),
new (webpack.optimize.OccurenceOrderPlugin || webpack.optimize.OccurrenceOrderPlugin)(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.DefinePlugin({
'process.env.BROWSER': true,
}),
],
};
here my server.js :
app.use(
require("webpack-dev-middleware")(compiler, {
noInfo: true,
publicPath: webpackConfig.output.publicPath
})
);
app.use(require("webpack-hot-middleware")(compiler));
// main route
app.get("/", (req, res) =>{
res.sendFile(path.resolve(__dirname, "./public/index.html"))
compiler.outputFileSystem.readFile(filename, (err, result) => {
if (err) {
return next(err);
}
res.set('content-type', 'text/html');
res.send(result);
res.end();
});
});
my package.json :
"scripts": {
"starter": "nodemon ./starter.js",
"start-dev": "concurrently --kill-others 'npm run webpack' 'npm run devserver'",
"devserver": "NODE_ENV=development nodemon ./server.js",
"webpack": "NODE_ENV=development webpack --w --hot --inline",
"start": "NODE_ENV=production webpack & NODE_ENV=production node ./server.js "
}
Any hint would be great,
Thanks
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.
I recently changed the name of my root directory (where package.json and webpack.config.js sits) and now webpack-dev-server is not updating anytime I change my files.
Here's my webpack config:
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
module.exports = {
context: path.join(__dirname, "src"),
devtool: debug ? "inline-sourcemap" : null,
entry: "./js/init.js",
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: ['react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy'],
}
}
]
},
output: {
path: __dirname + "/src/",
filename: "app.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
devServer: {
port: 3000,
hot: true,
historyApiFallback: {
index: 'index.html'
}
}
};
And my directory looks like this (Client React is the folder that had its name changed):
Let me clarify that this worked fine before, so I really have no idea why this isn't working now.
Edit: Scripts in package.json
"scripts": {
"dev": "./node_modules/.bin/webpack-dev-server --content-base src --inline --hot",
"build": "webpack"
},
You have to remove the brackets. Probably because they are not properly escaped by the watch module that webpack uses (watchpack) or the part that does the final watching in the System itself. I recommend you don't use any special characters inside directory- or filenames because of such bugs.