Recently i am learning webpack with react and i build a app that runs wells in Dev enviroment but when i build the app and tries to change the route it throws 404 error.
Here are my webpack Config.
webpack.common.js
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
entry: path.resolve(__dirname, "..", "./src/index.tsx"),
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js"],
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
},
],
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test:/\.(?:ico|gif|png|jpg|jpeg)$/i,
type:'asset/resource'
},
{
test:/\.(woff(2)?|eot|ttf|otf|svg)$/i,
type:'asset/inline'
}
],
},
output: {
path: path.resolve(__dirname, "..", "./build"),
filename: "bundle.js",
},
plugins: [
new HTMLWebpackPlugin({
template: path.resolve(__dirname, "..", "./public/index.html"),
filename:'index.html'
}),
// new CopyWebpackPlugin({
// patterns:[{from:"src",to:'dest'}]
// })
],
};
webpack.dev.js
const ReactRefreshWebpackPlugin = require('#pmmmwh/react-refresh-webpack-plugin');
const path=require('path')
module.exports={
mode:"development",
devServer:{
hot:true,
open:true,
historyApiFallback: { index: "/", disableDotRule: true },
port:3001
},
devtool:'cheap-module-source-map',
plugins:[
new ReactRefreshWebpackPlugin()
]
}
webpack.prod.js
module.exports={
mode:"production" ,
}
i changed lots of configuration like public path and other, but it didn't help.
Related
I have spent days getting to my current Webpack configuration setup.
When Webpack runs the build, the file size of my minified output file "react_customer.uniqueid.js" ends up being 2.53 MB, I would be satisfied if the file size would be under 1 MB.
Here is a visualization of the bundled JavaScript.
Could this setup be optimized further so the file size gets reduced?
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const nodeExternals = require("webpack-node-externals");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const { EnvironmentPlugin } = require("webpack");
module.exports = {
mode: "production",
entry: {
react_customer: path.resolve(__dirname, "react-customer/index.js"),
react_admin: path.resolve(__dirname, "react-admin/index.js"),
},
output: {
path: path.resolve(__dirname, "production-build"),
filename: "[name].[contenthash].js",
assetModuleFilename: "[name][ext]",
clean: true,
publicPath: "/",
},
//externals: [nodeExternals()],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.uglifyJsMinify,
// `terserOptions` options will be passed to `uglify-js`
// Link to options - https://github.com/mishoo/UglifyJS#minify-options
terserOptions: {},
}),
],
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, /*"style-loader",*/ "css-loader"],
},
{ test: /\.(svg|ico|png|webp|jpg|gif|jpeg)$/, type: "asset/resource" },
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
["#babel/preset-env", { modules: false }],
["#babel/preset-react", { runtime: "automatic" }],
],
},
},
},
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
//"style-loader",
MiniCssExtractPlugin.loader,
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
],
},
plugins: [
new EnvironmentPlugin({
backend_server: "https://www.example.com",
frontend_customer: "https://www.example.com",
}),
new BundleAnalyzerPlugin(),
new MiniCssExtractPlugin(),
new HtmlWebpackPlugin({
filename: "index.html",
template: path.resolve(
__dirname,
"server/templates/other/react-customer-template.html"
),
chunks: ["react_customer"],
}),
new HtmlWebpackPlugin({
filename: "admin.html",
template: path.resolve(
__dirname,
"server/templates/other/react-admin-template.html"
),
chunks: ["react_admin"],
}),
],
};
I was using webpack 3, there was no hot reload issue and then I upgraded to webpack 5.
Webpack version: ^5.50.0, React version: 17.0.2
Webpack source map doesn't work properly. I attached a picture of output at the bottom.
When I read webpack documentation, there is no difference between my config with offical config.
Here is my webpack hot config for development;
const webpack = require('webpack') //to access built-in plugins
const HtmlWebpackPlugin = require('html-webpack-plugin') //installed via npm
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const CopyPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const vendorArray = require('./vendors')
const path = require('path')
const Dotenv = require('dotenv-webpack')
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: {
main: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://0.0.0.0:3002',
'webpack/hot/only-dev-server',
'./src/main.js'
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash:8].js'
},
resolve: {
extensions: ['.js', '.jsx', '.css', '.scss', '.json']
},
module: {
rules: [
{
test: /\.js?$/,
exclude: /(node_modules|bower_components)/,
loader: './config/webpack/style-loader'
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [['#babel/preset-env', { targets: 'defaults' }], '#babel/preset-react'],
plugins: [
'#babel/plugin-transform-runtime',
'#babel/plugin-proposal-class-properties',
'#babel/plugin-proposal-optional-chaining',
'#babel/plugin-proposal-nullish-coalescing-operator',
[
'#babel/plugin-proposal-decorators',
{
legacy: true
}
]
]
}
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']
},
{
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)([\?]?.*)$/,
type: 'asset/resource'
}
]
},
plugins: [
new webpack.DefinePlugin({
APP_ENV: JSON.stringify('dev')
}),
new HtmlWebpackPlugin({
template: './public/index.html',
templateParameters: {
recaptchaSiteKey: '6LfbRrEZAAAAAL1EiyUSq1yzEw1xqleak2xC2pzi',
intranetLogin: true
}
}),
new MiniCssExtractPlugin(),
new Dotenv({
path: path.resolve(__dirname, './../../.env.test')
})
]
}
When building my react application i get a error that webpack/bootstrap is trying to access {n}.budle.js files that dosn't exist in my dist folder. I only get this error when uploading to a server locally the code is not trying to access these files in dist folder.
Error
Files in dist, no budle files
Webpack.prod.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
mode: "production",
entry: {
index: "./src/index.tsx"
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js',
},
devtool: "source-map",
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "Template",
template: path.join(__dirname, 'index.html')
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({ log: (t) => console.log(t) }),
],
module: {
rules: [
{
test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/,
use: "url-loader?limit=100000"
},
{ test: /\.(js|jsx|ts|tsx)?/, include: [path.join(__dirname, 'src')], use: { loader: 'babel-loader' } },
{ test: /\.css$/i, use: ['style-loader', 'css-loader'], },
]
},
resolve: {
enforceExtension: false,
extensions: [".jsx", ".js", ".tsx", ".ts", ".json", ".png"],
alias: {
"~": path.resolve(__dirname, 'src/'),
},
}
}
The entry point to the site is site.com/something/index.html is that a issue?
Building TS/SASS with Webpack works fine, running this through VSCode Live Server plugin renders the index.html perfectly to the app folder.
Running webpack-dev-server with it looking at the same app folder does not. The page opens but there is a Javascript error Uncaught SyntaxError: Unexpected token '<'
And the page does not render the JS/CSS.
webpack.config.js
// Imports
var path = require("path");
// Plugins
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// Exports
module.exports = {
mode: 'development',
entry: './src/main.ts',
devtool: "inline-source-map",
resolve: {
extensions: [".ts", ".tsx", ".js"]
},
output: {
filename: 'main.min.js',
path: path.resolve(__dirname, 'app')
},
devServer: {
open: 'http://localhost',
port: 80,
publicPath: path.resolve(__dirname, 'app'),
hot: true
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: { minimize: true }
}
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
"sass-loader"
]
},
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
]
}
tsconfig.json
{
"compilerOptions": {
"sourceMap": true
}
}
main.ts
console.log('Main.ts has loaded')
import './styles/main.scss'
Any help with this would be appreciated, I'm losing my mind lol.
My issue was with syntax in the webpack.config.js file.
I was neglecting to insert a comma at the end of the last entry in every object and array, believing it not to be necessary.
Here is a working config:
// Imports
var path = require("path");
// Plugins
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// Exports
module.exports = {
mode: 'development',
entry: './src/main.ts',
devtool: "inline-source-map",
output: {
filename: 'main.min.js',
path: path.resolve(__dirname, 'app'),
},
devServer: {
open: 'http://localhost',
port: 80,
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: { minimize: true },
}
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader',
]
},
{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
"sass-loader",
]
},
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html",
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css",
}),
]
}
I setup a webpack config to build server.build and client.build, but they both producing different css/locals.
webpack.server.js
const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const serverConfig = {
name: 'server',
target: 'node',
externals: [nodeExternals()],
entry: [
__dirname+'/index.js'
],
output: {
path: path.join(__dirname, '/.build'),
filename: 'server.build.js',
publicPath: '.build/',
libraryTarget: 'commonjs2'
},
module: {
loaders: [
{
test:/\.(?:js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.(?:css|less)$/,
use: "css-loader/locals?import=1&modules=1&localIdentName=[name]__[local]__[hash:base64:7]",
exclude: /\.(eot|woff|woff2|ttf|svg)(\?[\s\S]+)?$/
},
{
test: /\.(eot|woff|woff2|ttf|svg)(\?[\s\S]+)?$/,
loader: 'url-loader?limit=1000&name=./fonts/[name].[ext]?[hash:base64:5]#icomoon',
}
]
},
resolve: {
extensions: ['.jsx', '.js', '.json','.less']
}
};
module.exports = serverConfig;
webpack.client.js
const webpack = require('webpack');
const path = require('path');
const context = path.resolve(__dirname, 'src');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const config = {
name:"client",
context,
entry: __dirname+'/src/app.js',
output: {
path: __dirname+"/.build/assets",
filename: 'bundle.js'
},
devtool: "source-map",
module: {
rules: [
{
test:/\.(?:js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.(?:css|less)$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader?module',
options: {
sourceMap: true,
importLoader: true,
localIdentName:'[name]__[local]__[hash:base64:7]'
}
},
{
loader: 'less-loader',
options: {
sourceMap: true,
importLoader: true,
}
}
],
fallback: 'style-loader',
}),
exclude: /\.(eot|woff|woff2|ttf|svg)(\?[\s\S]+)?$/
},
{
test: /\.(eot|woff|woff2|ttf|svg)(\?[\s\S]+)?$/,
loader: 'url-loader?limit=1000&name=./fonts/[name].[ext]?[hash:base64:5]#icomoon',
}
]
},
plugins: [
new ExtractTextPlugin({
filename: 'bundle.css',
allChunks: true,
}),
new webpack.DefinePlugin({
"process.env": {
BROWSER: JSON.stringify(true),
NODE_ENV: JSON.stringify("production")
}
}),
],
resolve: {
extensions: ['.jsx', '.js', '.json']
}
};
module.exports = config;
Ex: server.build.js -> style__cont__2KTI-wF
bundle.js/bundle.css (client) -> style__cont__58B3ts_
I am really stuck at this point, i am new to react and there is no perfect approach to import css server side.