How i can solve the devServer problem in webpack? - javascript

I would be grateful for any help or advice. I have compiled the configuration of the webpack, everything works in production mode, but the webpack-dev-server does not see static files and gives the error "Cannot get /". How can I solve this problem? Thank you in advance for the answer. Here is my webpack.config.js
const path = require("path");
const { VueLoaderPlugin } = require("vue-loader");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin");
const TerserWebpackPlugin = require("terser-webpack-plugin");
// const autoprefixer = require("autoprefixer");
const isProd = process.env.NODE_ENV === "production";
const isDev = !isProd;
const optimization = () => {
const config = {
runtimeChunk: "single",
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
priority: -10,
chunks: "all",
},
},
},
};
if (isProd) {
config.minimizer = [
new CssMinimizerWebpackPlugin(),
new TerserWebpackPlugin(),
];
}
return config;
};
module.exports = {
entry: path.resolve(__dirname, "src", "index.js"),
mode: isProd ? "production" : "development",
output: {
path: path.join(__dirname, "build"),
filename: "[name].[contenthash:8].js",
chunkFilename: "[name].[contenthash:8].js",
publicPath: "./",
},
devtool: isDev ? "source-map" : false,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.vue$/,
loader: "vue-loader",
},
{
test: /\.(eot|ttf|woff|woff2)(\?\S*)?$/,
loader: "file-loader",
options: {
name: "[name][contenthash:8].[ext]",
},
},
{
test: /\.(png|jpe?g|gif|webm|mp4|svg)$/,
loader: "file-loader",
options: {
name: "[name][contenthash:8].[ext]",
outputPath: "assets/img",
esModule: false,
},
},
{
test: /\.s?css$/,
use: [
"style-loader",
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: false,
},
},
"css-loader",
],
},
],
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "[name].[contenthash:8].css",
chunkFilename: "[name].[contenthash:8].css",
}),
new HTMLWebpackPlugin({
template: path.join(__dirname, "src", "public", "index.html"),
filename: "start-page.html",
alwaysWriteToDisk: true,
minify: {
collapseWhitespace: isProd,
},
}),
new CleanWebpackPlugin(),
],
resolve: {
alias: {
vue: "#vue/runtime-dom",
},
extensions: ["*", ".js", ".vue", ".json"],
},
optimization: optimization(),
devServer: {
compress: true,
port: 9000,
hot: true,
client: {
overlay: true,
},
},
};
Here is a project folders

According to the doc, you need to set the publicPath in the devServer.
Look at the documentation
module.exports = {
//...
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 9000,
},
};

Related

Webpack 5 SCSS and JS save returns old version of page

I work with webpack 5. Pug works well - after autosave or cmd+S I get new version of page. And it doesn't work so with JS and SCSS: SCSS autosave works well but after cmd+S I get some old version of page(usually everytime the same). With JS both autosave and cmd+S return some old version of page. Can you help me to find a solution? Below I dropped webpack.config.js
const path = require("path");
const fs = require("fs");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const isDev = process.env.NODE_ENV === "development";
const isProd = !isDev;
const PATHS = {
src: path.join(__dirname, "./src"),
dist: path.join(__dirname, "./dist"),
};
const PAGES_DIR = `${PATHS.src}/`;
const PAGES = fs.readdirSync(PAGES_DIR).filter((fileName) => fileName.endsWith(".pug"));
const filename = (ext) => `[name].${ext}`;
const plugins = () => {
const basePlugins = [
...PAGES.map(
(page) =>
new HTMLWebpackPlugin({
template: `${PAGES_DIR}/${page}`,
filename: `./${page.replace(/\.pug/, ".html")}`,
})
),
new MiniCssExtractPlugin({
filename: `./css/${filename("css")}`,
}),
new CopyWebpackPlugin({
patterns: [
{ from: path.resolve(__dirname, "src/assets"), to: path.resolve(`${PATHS.dist}`) },
{ from: path.resolve(__dirname, "src/img"), to: path.resolve(`${PATHS.dist}/img/`) },
],
}),
];
return basePlugins;
};
module.exports = {
context: path.resolve(`${PATHS.src}`),
mode: "development",
entry: "./js/main.js",
output: {
filename: `./js/${filename("js")}`,
path: path.resolve(`${PATHS.dist}`),
publicPath: "",
clean: true,
},
devServer: {
historyApiFallback: true,
static: path.resolve(`${PATHS.dist}`),
open: true,
compress: true,
hot: true,
port: 3000,
},
optimization: {
splitChunks: {
chunks: "all",
},
},
plugins: plugins(),
devtool: isProd ? false : "source-map",
module: {
rules: [
{
test: /\.pug$/,
loader: "pug-loader",
},
{
test: /\.s[ac]ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
return path.relative(path.dirname(resourcePath), context) + "/";
},
},
},
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: ["postcss-preset-env"],
},
},
},
"sass-loader",
],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.(?:|gif|png|jpg|jpeg|svg|webp)$/,
use: [
{
loader: "file-loader",
options: {
name: `./img/${filename("[ext]")}`,
},
},
],
},
{
test: /\.(?:|woff2)$/,
use: [
{
loader: "file-loader",
options: {
name: `./fonts/${filename("[ext]")}`,
},
},
],
},
],
},
};
I don't know what to write here. I described my problem above.

Webpack 5 not showing images

I have a vue 3 app where I set up webpack 5 eventually. As I see I eliminated all my issues now the only thing remains is that it does not load my svg-s and images when I run the webpack serve script in dev mode. How can I configure webpack so that it would bundle my svg-s from the scr/assets folder?
my webpack config:
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const env = process.env.NODE_ENV || 'development';
const mode = process.env.VUE_APP_MODE || 'not-fullstack';
module.exports = {
mode: 'development',
entry: './src/main.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
resolve: {
alias: {
vue: '#vue/runtime-dom',
'#': path.join(__dirname, 'src'),
},
fallback: { crypto: false, stream: false },
},
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
},
],
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader', 'postcss-loader'],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'images/[name].[hash].[ext]',
},
type: 'asset/resource',
},
{
test: /\.svg$/i,
use: [
{
loader: 'url-loader',
options: {
encoding: false,
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.resolve(__dirname, './public/index.html'),
}),
new VueLoaderPlugin(),
new CopyPlugin([
{ noErrorOnMissing: true, from: './src/assets', to: 'images' },
]),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(env),
'process.env.VUE_APP_MODE': JSON.stringify(mode),
}),
],
devServer: {
historyApiFallback: true,
compress: true,
port: 3000,
},
};
And I reference my svg-s in my Vue component like this:
<img src="../../assets/logo.svg" alt="logo" />
As you can see I tried with the copy-webpack-plugin, maybe I just configured it wrong.
Thank you for your help in advance!
The config in webpack5 changed a lot
{
loader: 'url-loader',
options: {
encoding: false,
},
This is not working anymore. The url-loader is even removed from the npm packages.
The current way is found in the documentation
https://webpack.js.org/guides/asset-management/#loading-images

Webpack unexpected behavior TypeError: Cannot read property 'call' of undefined

Recently we have updated webpack to v4 and soon noticed unexpected errors from webpack during development, which disappears after rebuild of entire bundle.
Our application build using lazy loading and code splitting, which can cause the issue, though I couldn't find anything related to this in the official documentations.
Here the error we get
react_devtools_backend.js:2273 TypeError: Cannot read property 'call' of undefined
our webpack webpack.config.js file.
const webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const AssetsPlugin = require('assets-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
// minification plugins
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// image optimization plugins
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const imageminGifsicle = require("imagemin-gifsicle");
const imageminPngquant = require("imagemin-pngquant");
const imageminSvgo = require("imagemin-svgo");
const imageminMozjpeg = require('imagemin-mozjpeg');
const env = require('dotenv').config();
const isProd = process.env.NODE_ENV === 'production';
const isDev = !isProd;
const environment = {
NODE_ENV: process.env.NODE_ENV || 'development',
CONFIG: process.env.CONFIG || 'development',
DEBUG: process.env.DEBUG || false,
};
const plugins = () => {
let plugins = [
new CleanWebpackPlugin(['build', 'cachedImages'], {
root: path.resolve(__dirname, '../dist'),
verbose: true,
dry: false,
}),
new webpack.EnvironmentPlugin(Object.assign(environment, env.parsed)),
new MiniCssExtractPlugin('[chunkhash:5].[name].[hash].css'),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
moment: 'moment',
_: 'lodash',
}),
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en)$/),
new AssetsPlugin({
filename: 'assets.json',
}),
new ImageminPlugin({
cacheFolder: isDev ? path.resolve(__dirname, '../dist/cachedImages') : null,
externalImages: {
context: 'src',
sources: glob.sync('src/assets/img/**/*.*'),
destination: 'dist/img/',
fileName: (filepath) => {
let name = filepath.split(/img(\/|\\)/).pop();
return name;
},
},
plugins: [
imageminGifsicle({
interlaced: false
}),
imageminMozjpeg({
progressive: true,
arithmetic: false
}),
imageminPngquant({
floyd: 0.5,
speed: 2
}),
imageminSvgo({
plugins: [
{ removeTitle: true },
{ convertPathData: false }
]
}),
],
}),
];
if (isProd) {
plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'static',
reportFilename: path.resolve(__dirname, 'analysis.html'),
generateStatsFile: false,
logLevel: 'info',
})
);
}
return plugins;
};
const optimization = () => {
let optimizations = {
concatenateModules: true,
splitChunks: {
cacheGroups: {
vendor: {
name: 'vendor',
test: /[\\/]node_modules[\\/](react|react-dom|lodash|moment)[\\/]/,
chunks: 'all',
},
commons: {
chunks: 'async',
}
}
}
};
if (isProd) {
optimizations.minimizer = [
new TerserJSPlugin({
terserOptions: {
compress: {
pure_funcs: ['console.log'],
drop_console: true,
drop_debugger: true
},
warnings: false
},
parallel: true
}),
new OptimizeCSSAssetsPlugin({})
];
}
return optimizations;
};
const fontLoaders = [
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url?limit=10000&mimetype=application/font-woff',
}
},
{
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url?limit=10000&mimetype=application/font-woff',
}
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url?limit=10000&mimetype=application/octet-stream',
}
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url?limit=10000&mimetype=image/svg+xml',
}
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'file',
}
}
];
const config = {
mode: process.env.NODE_ENV,
devtool: isDev ? 'source-map' : '',
context: path.resolve(__dirname, '../src'),
entry: {
bundle: './app.jsx',
embed: './embed.jsx',
styles: './sass_new/main.scss',
vendor: [
'react',
'react-dom',
'redux',
'redux-saga',
'react-redux',
'react-router',
'react-tap-event-plugin',
'lodash',
'moment',
]
},
output: {
publicPath: '/build/',
filename: '[name].[hash].js',
chunkFilename: '[name].[hash].js',
path: path.resolve(__dirname, '../dist/build'),
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
config: path.resolve(__dirname, '../config.js'),
utils: path.resolve(__dirname, '../src/utils'),
shared: path.resolve(__dirname, '../src/components/shared'),
services: path.resolve(__dirname, '../src/services'),
store: path.resolve(__dirname, '../src/store'),
constants: path.resolve(__dirname, '../src/constants'),
actions: path.resolve(__dirname, '../src/actions'),
components: path.resolve(__dirname, '../src/components'),
},
},
optimization: optimization(),
plugins: plugins(),
module: {
rules: [
{
test: /\.jsx?$/,
exclude: [/node_modules/, /libs/],
use: {
loader: path.join(__dirname, '../helpers/custom-loader.js'),
options: {
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: [
'#babel/plugin-proposal-object-rest-spread',
'#babel/plugin-proposal-class-properties',
'#babel/plugin-transform-destructuring',
'#babel/plugin-syntax-dynamic-import',
'#babel/plugin-transform-runtime',
'syntax-async-functions'
]
}
}
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
'sass-loader',
]
},
{
test: /\.css$/,
use: [
'css-loader'
]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: "url-loader",
options: {
name: "[path][name].[ext]"
},
},
...fontLoaders
]
},
watchOptions: {
ignored: /node_modules/,
},
};
module.exports = config;
I have no idea how to fix this, and it's taking a lot of time to rebuild entire app after getting this error.

React + Webpack: "RuntimeError: memory access out of bounds"

I've recently developed a react + webpack application that is deployed using
AWS Amplify. I've been getting a strange error that is logged on Sentry, but can't
find a way to replicate the bug.
RuntimeError: memory access out of bounds
I suspect it has something to do with my webpack configuration, but I don't know whats wrong.
I never used wasm, but it seems to be related to it.
Here is my production level webpack configuration.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const env = require('../environment/prod.env');
const commonPaths = require('./paths');
const webpack = require('webpack');
const SentryWebpackPlugin = require('#sentry/webpack-plugin');
module.exports = {
mode: 'production',
devtool: 'source-map',
output: {
filename: `${commonPaths.jsFolder}/[name].[hash].js`,
path: commonPaths.outputPath,
chunkFilename: `${commonPaths.jsFolder}/[name].[chunkhash].js`,
},
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
cache: true,
sourceMap: true,
}),
new OptimizeCSSAssetsPlugin(),
],
splitChunks: {
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'initial',
},
async: {
test: /[\\/]node_modules[\\/]/,
name: 'async',
chunks: 'async',
minChunks: 4,
},
},
},
runtimeChunk: true,
},
module: {
rules: [
{
test: /\.scss$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env': env,
}),
new MiniCssExtractPlugin({
filename: `${commonPaths.cssFolder}/[name].css`,
chunkFilename: `${commonPaths.cssFolder}/[name].css`,
}),
],
};
Here is also my common webpack configuration
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const commonPaths = require('./paths');
module.exports = {
context: commonPaths.srcPath,
entry: commonPaths.entryPath,
output: {
path: commonPaths.outputPath,
filename: 'js/[name].js',
},
resolve: {
extensions: ['.ts', '.js', '.html', '.vue'],
alias: {
'~': commonPaths.srcPath,
},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
include: commonPaths.srcPath,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
plugins: ['react-hot-loader/babel'],
},
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/img/[name].[hash:8].[ext]',
publicPath: '/',
},
},
],
},
{
test: /\.(mp3)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/audio/[name].[hash:8].[ext]',
publicPath: '/',
},
},
],
},
{
test: /\.(ttc|ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/fonts/[name].[hash:8].[ext]',
publicPath: '/',
},
},
],
},
],
},
serve: {
content: commonPaths.entryPath,
dev: {
publicPath: commonPaths.outputPath,
},
open: true,
},
resolve: {
modules: ['src', 'node_modules', 'bower_components', 'shared', '/shared/vendor/modules'],
extensions: ['*', '.js', '.jsx'],
},
plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({
favicon: './icon.png',
template: commonPaths.templatePath,
}),
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'async',
}),
],
};
Any help would really help. Thanks.
Try to restart your server and make sure you reinstall node modules.

No sourcemap for js with ExtractTextPlugin

With this config I get an app.bundle.js, app.map, app.css. The problem is that app.map contains only the css related code. If I don't use ExtractTextPlugin then the sourcemap contains all the css and js related code but I have to keep css in a separate file. If I don't get map for css that's fine but for js it is a must have.
// webpack.common.config
var webpack = require('webpack');
var helpers = require('./helpers');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackPostcssTools = require('webpack-postcss-tools');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var autoprefixer = require('autoprefixer');
var postcssImport = require('postcss-import');
var map = webpackPostcssTools.makeVarMap('src/css/index.css');
var ngAnnotatePlugin = require('ng-annotate-webpack-plugin');
const METADATA = {
baseUrl: '/'
};
module.exports = {
metadata: METADATA,
entry: {
'app': './src/js/app.js',
'vendor': './src/vendor.js'
},
resolve: {
extensions: ['', '.js'],
root: helpers.root('src'),
modulesDirectories: ['node_modules']
},
module: {
preLoaders: [
{ test: /\.js$/, loaders:['eslint', 'source-map-loader'], exclude: /node_modules/ }
],
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css?sourceMap&importLoaders=1!postcss-loader?sourceMap')
},
{
test: /\.html$/,
loader: 'raw-loader',
exclude: [helpers.root('src/index.html')]
},
{
test: /\.woff(\?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"
}
]
},
plugins: [
new ngAnnotatePlugin({
add: true,
}),
new ExtractTextPlugin("[name].css", { allChunks: true }),
new webpack.optimize.OccurenceOrderPlugin(true),
new webpack.optimize.CommonsChunkPlugin({
name: helpers.reverse(['vendor', 'app']),
minChunks: Infinity
}),
new CopyWebpackPlugin([{
from: 'src/res',
to: 'res'
}, {
from: 'src/templates',
to: 'templates'
}
}
]),
new HtmlWebpackPlugin({
template: 'src/index.html',
chunksSortMode: 'none'
}),
],
postcss: function (webpack) {
return [
//webpackPostcssTools.prependTildesToImports,
postcssImport({ addDependencyTo: webpack }),
require('postcss-custom-properties')({
variables: map.vars
}),
require('postcss-custom-media')({
extensions: map.media
}),
require('postcss-calc'),
autoprefixer
];
},
node: {
global: 'window',
crypto: 'empty',
module: false,
clearImmediate: false,
setImmediate: false
},
};
// webpack.dev.config
var helpers = require('./helpers');
var webpackMerge = require('webpack-merge');
var commonConfig = require('./webpack.common.js');
var DefinePlugin = require('webpack/lib/DefinePlugin');
const ENV = process.env.ENV = process.env.NODE_ENV = 'development';
const METADATA = webpackMerge(commonConfig.metadata, {
host: 'localhost',
port: 8000,
ENV: ENV
});
module.exports = webpackMerge(commonConfig, {
debug: true,
metadata: METADATA,
devtool: 'source-map',
output: {
path: helpers.root('www'),
filename: '[name].bundle.js',
sourceMapFilename: '[name].map',
chunkFilename: '[id].chunk.js'
},
plugins: [
new DefinePlugin({
'ENV': JSON.stringify(METADATA.ENV)
}),
],
devServer: {
port: METADATA.port,
host: METADATA.host,
historyApiFallback: true,
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
},
eslint: {
configFile: './.eslintrc.js',
emitError: false,
emitWarning: false,
fix: true
},
node: {
global: 'window',
crypto: 'empty',
process: true,
module: false,
clearImmediate: false,
setImmediate: false
}
});
The issue seems to be that ExtractTextPlugin overwrites other sourcemaps, according to this discussion: https://github.com/webpack/extract-text-webpack-plugin/issues/119
You can fix this issue by ensuring that each output file that gets a sourcemap gets a different filename, like this:
sourceMapFilename: '[file].map'

Categories

Resources