I am trying to get a project running that uses a webpack dev server with HMR and source-mapping but am running into an issue. When I use webpack alone with my configuration file the source-maps are indicated in the console output and HMR works on page-refresh, but there is no server. When I try to instead run the script using webpack-dev-server there is no indication in the console that source-maps are being generated and changes are not being rendered ( either automatically or on page refresh ) when recompilation is appearing in the console output.
Here is my configuration file
/*
Webpack Configuration File
webpack.config.js
===
Webpack configuration file for the, "Debugging Webpack Issues" project.
#version:0.1.1
*/
const webpack = require( "webpack" );
const path = require( "path" );
const htmlWebpackPlugin = require( "html-webpack-plugin" );
const BUILD_PATH = path.resolve( __dirname, "../build" );
const SOURCE_PATH = path.resolve( __dirname, "../src" );
console.log(BUILD_PATH);
console.log(SOURCE_PATH);
let config = {
entry: SOURCE_PATH + "/index.js",
output: {
path: BUILD_PATH + "/rsc/scripts/",
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
options: {
"presets" : [ "es2015", "react" ]
},
exclude: [/node_modules/],
include: SOURCE_PATH
},
{
test: /\.css$/,
use: [ "style-loader", "css-loader" ],
include: SOURCE_PATH,
exclude: [/node_modules/]
}
]
},
devServer: {
compress: true,
port:9000,
open: true,
hot: true,
contentBase: BUILD_PATH
},
devtool: "source-map",
watch: true,
target: "web",
plugins: [
new htmlWebpackPlugin({
title: "Example React App",
filename: "../../index.html",
template: SOURCE_PATH + "/template.html"
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
]
};
module.exports = config;
I am aware that webpack-dev-server may not be updating because it is trying to load from a static location, but I have attempted changes to my file that others specified in their projects ( such as adding publicPath to the file ) with this issue without success.
Webpack's publicPath value needs to be relative to the build directory in the output.
Here is a working version of my webpack configuration file :
/*
Webpack Configuration File
webpack.config.js
===
Webpack configuration file for the, "Debugging Webpack Issues" project.
#version:0.1.1
*/
const webpack = require( "webpack" );
const path = require( "path" );
const htmlWebpackPlugin = require( "html-webpack-plugin" );
const BUILD_PATH = path.resolve( __dirname, "../build" );
const SOURCE_PATH = path.resolve( __dirname, "../src" );
const PUBLIC_PATH = "/rsc/scripts/";
console.log(BUILD_PATH);
console.log(SOURCE_PATH);
let config = {
entry: SOURCE_PATH + "/index.js",
output: {
path: BUILD_PATH + PUBLIC_PATH,
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
options: {
"presets" : [ "es2015", "react" ]
},
exclude: [/node_modules/],
include: SOURCE_PATH
},
{
test: /\.css$/,
use: [ "style-loader", "css-loader" ],
include: SOURCE_PATH,
exclude: [/node_modules/]
}
]
},
devServer: {
compress: true,
port:9000,
open: true,
hot: true,
contentBase: BUILD_PATH,
publicPath: PUBLIC_PATH
},
devtool: "source-map",
watch: true,
target: "web",
plugins: [
new htmlWebpackPlugin({
title: "Example React App",
filename: "../../index.html",
template: SOURCE_PATH + "/template.html"
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
]
};
module.exports = config;
Anyone with this problem should make sure that a publicPath is set in the devServer configuration options. The publicPath should be treated as the path ( relative to the build directory ) that your Server's html file should look to grab bundle.js from.
My project structure in my Build folder looks like:
./build
./build/rsc/scripts/bundle.js
./build/index.html
so my publicPath needed to be set to /rsc/scripts so that it knew where to get the virtual file from.
In my case , project was generated by create-react-app.
My solution is:
Find
./node_modules/react-scripts/config/webpackDevServer.config.js
locate below code:
historyApiFallback: {
// Paths with dots should still use the history fallback.
// See https://github.com/facebook/create-react-app/issues/387.
disableDotRule: true,
index: paths.publicUrlOrPath,
},
Remove the above code, and update the above as below:
historyApiFallback: true,
hot: true,
Related
I am trying to create JavaScript Library and CSS bundle (extracting all CSS used in a single file) using webpack 4.
My webpack.config.js file configuration is as below:
var path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin"); // Require to generate html file
var MiniCssExtractPlugin = require("mini-css-extract-plugin"); // Require to generate css file
module.exports = {
entry: __dirname + "/src/app/index.js", // webpack entry point. Module to start building dependency graph
output: {
path: path.join(__dirname, "dist"), // Folder to store generated bundle
filename: "chart.min.js", // Name of generated bundle after build
library: ["Chart"],
libraryTarget: "umd"
},
module: { // where we defined file patterns and their loaders
rules: [
{
test: /\.js$/,
use: "babel-loader",
exclude: [
/node_modules/
]
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
],
exclude: [
/node_modules/
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: "chart",
test: /\.css$/,
chunks: "all",
enforce: true
}
}
}
},
plugins: [ // Array of plugins to apply to build chunk
new HtmlWebpackPlugin({
template: __dirname + "/src/public/index.html",
inject: "body"
}),
new MiniCssExtractPlugin({
filename: "[name].css"
})
],
devServer: { // configuration for webpack-dev-server
contentBase: "./src/public", //source of static assets
port: 7700 // port to run dev-server
}
};
By running above code, I am getting following files in my dist folder
"1.chart.min.js", "chart.min.js", "chart.css", "index.html"
May I know why I am getting "1.chart.min.js" file and How can I stop generating same?
You may like to clean the output path using clean-webpack-plugin
Here is my folder structure:
I want to minify and bundle the CSS files inside my src/css folder and output it as a single CSS file inside dist. All the examples I've seen so far recommend require-ing the CSS file inside a JS file. I do not want that. Is there a way to configure in webpack.config.js to just minify and copy these files?
Got it working.
Install dev-dependecies
npm i extract-text-webpack-plugin --save-dev
npm i css-loader --save-dev
webpack.config.js
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const extractCSS = new ExtractTextPlugin('bundle.min.css')
module.exports = {
entry: {
'bundle.min.css': [
__dirname + '/src/styles/abc.css',
__dirname + '/src/styles/xyz.css',
__dirname + '/src/styles/mno.css'
]
},
devtool: '',
output: {
path: __dirname + '/dist/styles/',
filename: '[name]'
},
module: {
rules: [{
test: /\.css$/i,
use: extractCSS.extract({
use: {
loader: 'css-loader',
options: {
minimize: true
}
}
})
}]
},
resolve: {
alias: {},
modules: [],
extensions: ['.css']
},
plugins: [
extractCSS
]
};
bundle.min.css will get generated. Based on minimize: true/false, minification will be decided. Enjoy!
It will go in three steps;
first you will need two loaders and plugin; named css-loader and style-loader and extract-text-webpack-plugin respectively.
Then your config might look like following:
const webpack = require('webpack');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const path = require('path');
module.exports = {
entry: {
app: './src/index.js'
},
output: {
path: 'dist',
filename: 'js/[name]-bundle.js'
},
devtool: "cheap-source-map",
resolveLoader: {
modules: [
'node_modules',
path.join(__dirname, '../node_modules'),
]
},
module: {
loaders: [
{
test: /.css?$/,
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }),
exclude: /node_modules/
}
]
},
plugins: [
new ExtractTextPlugin("css/[name].css"),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
screw_ie8: true,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
join_vars: true,
if_return: true
},
output: {
comments: false
}
}),
]
}
And then in your entry file, require them like require('./style.css');
Remember, it will follow the paths as your source.
If you are loading font files and images in you css, you might need the file-loader plugin as well which will copy all assets in directory.
The file-loader config will look like:
{
test: /.png?$/,
loader: 'file-loader?name=img/[name].[ext]',
exclude: /node_modules/
}
The UgligyJsPlugin will also minify the CSS.
I'm trying to create an universal react app (using webpack both on server and on the client) and struggle with images import. I want to write this :
import someImage from './someImage.png'
const SomeImage = () => <img src={someImage}/>
Here's my webpack config file:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: [
'webpack-dev-server/client?http://127.0.0.1:8080/',
'webpack/hot/only-dev-server',
'./client',
'babel-polyfill'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
modulesDirectories: ['node_modules', 'shared'],
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['babel']
},
{
test: /\.css/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'file?emitFile=false',
]
}
]
},
plugins: [
new ExtractTextPlugin('styles.css', { allChunks: true }),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
devtool: 'inline-source-map',
devServer: {
hot: true,
proxy: {
'*': 'http://127.0.0.1:' + (process.env.PORT || 3000)
},
host: '127.0.0.1'
}
};
Obviously it's not working server side because node try to read the content of the ./someImage.png file, resulting in an error.
How can I handle this ? I know there are packages such as webpack-isomorphic-tools or universal-webpack or even the file-loader package that can emit or not the file, but I don't understand of to use it in my universal app.
I'm using file-loader with emitFile: false to exclude assets from bundling on server side. Works as expected.
const imageRules = (emit = true) => ({
test: /\.(png|svg|jpeg|jpg|gif|ico)$/,
type: "asset",
generator: {
emit: emit,
},
});
Then use it in webpack client config:
module: {
rules: [imageRules()],
},
And in server config
module: {
rules: [imageRules(false)],
},
Today, after removing my node_modules and reinstalling them using npm install, my project doesn't seem to work.
Here's my webpack config
const webpack = require('webpack');
const path = require('path');
const srcPath = path.join(__dirname, './client');
const nodeEnv = process.env.NODE_ENV || 'development';
const isProd = nodeEnv === 'production';
module.exports = {
devtool: isProd ? 'hidden-source-map' : 'cheap-module-eval-source-map',
context: path.join(__dirname, './client'),
entry: {
js: './index.js',
vendor: ['react']
},
output: {
path: path.join(__dirname, './static'),
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.html$/,
loader: 'file',
query: {
name: '[name].[ext]'
}
},
{
test: /\.scss$/,
loaders: ['style', 'css', 'sass']
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loaders: ['babel-loader']
},
{
test: /\.(png|jpg|gif|otf|eot|svg|ttf|woff|woff2)/,
loader: 'url-loader'
},
{
test: /\.(txt|json)/,
loader: 'raw-loader'
}
],
},
resolve: {
extensions: ['', '.js', '.jsx'],
modules: [
path.resolve('./client'),
'node_modules'
],
alias: {
stores: `${srcPath}/stores/`,
components: `${srcPath}/components/`,
services: `${srcPath}/services`,
models: `${srcPath}/models`,
constants: `${srcPath}/constants`,
sources: `${srcPath}/sources`,
images: `${srcPath}/assets/images`,
appConstants: isProd ? `${srcPath}/constants/_prod` : `${srcPath}/constants/_dev`
}
},
plugins: [
new webpack.IgnorePlugin(/regenerator|nodent|js\-beautify/, /ajv/),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity,
filename: 'vendor.bundle.js'
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: isProd
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: !isProd
},
output: {
comments: !isProd
},
sourceMap: !isProd
}),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify(nodeEnv) }
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.OccurrenceOrderPlugin()
],
devServer: {
contentBase: './client',
hot: true,
port: 3000,
historyApiFallback: true
}
};
My "client" folder with index.html and the rest of my code are in the same folder as webpack config.
Webpack does succesfully build, but going to localhost:3000, I get error message: "Cannot GET /"
Going to localhost:3000/client/index.html does serve my index.html, but my built files inserted using
<script src="./vendor.bundle.js"></script>
<script src="./bundle.js"></script>
doesn't load (GET to "http://localhost:3000/client/bundle.js" results in 404)
Anyone knows what's going on? I can't fix this issue, and I think I've tried everything, from changing path, publicPath to changing contentBase and moving my static files to different folder.
It's very strange, since this issue appeared only after reinstalling my project dependencies.
Every bit of help is much appreciated. Thanks.
There was an issue in webpack-dev-server#2.1.0-beta.3, which caused the contentBase option to be ignored. Could you try upgrading to 2.1.0-beta.4? It was just released.
I'm trying to minimize my bundle.js file with webpack, but getting errors in my config:
module.exports = {
entry: "./entry.js",
output: {
devtoolLineToLine: true,
sourceMapFilename: "./bundle.js.map",
pathinfo: true,
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.css$/, loader: "style!css" }
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
include: /\.min\.js$/,
minimize: true
})
]
};
The error:
/Users/leongaban/Projects/TickerTags/ionic/TickerTags/www/webpack.config.js:16
new webpack.optimize.UglifyJsPlugin({
^
ReferenceError: webpack is not defined
Seems like you're missing var webpack = require('webpack'); at the top of your configuration file.
It works for me this way