Webpack (with React) hot loading not working - javascript

I have setup hot reloading with react-hot-loader. In the console it looks like it works, but browser does not actually reload. Why is this?
Ignore the errors, I think they come from a plugin. It correctly detects I change App.jsx but the browser does not update unless I do a full refresh.
My webpack.config.js below:
const path = require("path")
const webpack = require("webpack")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextPlugin = require("extract-text-webpack-plugin")
const context = path.resolve(__dirname, "src")
const {dependencies} = require("./package.json")
module.exports = {
context,
entry: {
vendor: Object.keys(dependencies),
app: [
"react-hot-loader/patch",
"./js/index.js"
]
},
output: {
path: path.resolve(__dirname, "build"),
filename: "[name]-[hash].js"
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
plugins: [
[
"react-css-modules",
{
context
}
]
]
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 1,
localIdentName: "[path]___[name]__[local]___[hash:base64:5]",
sourceMap: true
}
},
'postcss-loader'
]
})
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "vendor"
}),
new HtmlWebpackPlugin({
filename: "index.html",
template: "index.html"
}),
new webpack.NamedModulesPlugin(),
new ExtractTextPlugin("css/[name].css")
],
devServer: {
contentBase: path.resolve(__dirname, "src"),
historyApiFallback: true
},
devtool: "eval"
}
index.js
import ReactDOM from "react-dom"
import React from "react"
import {AppContainer} from "react-hot-loader"
import App from "./App.jsx"
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component />
</AppContainer>,
document.getElementById("app")
)
}
render(App)
if (module.hot) {
module.hot.accept("./App.jsx", () => render(App))
}

Related

MiniCssExtractPlugin can't reference async chucnks

I am using Vue with Webpack (without Vue CLI) and I ran into an issue.
I am building a Design System library, in which I would like to have async chunks so they get small.
When I import as usual the component in the index.ts of the lib
//index.ts
import RedBox from '#/components/RedBox.vue';
export { RedBox };
everything works perfectly.
But when I try to do
const RedBox = () => import('#/components/RedBox.vue');
export { RedBox };
i get
The file is actually there in the bundle.
Here is my webpack config
/* eslint-disable #typescript-eslint/no-var-requires */
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = (env) => {
const plugins = [
new VueLoaderPlugin(),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: 'assets/css/[name].css',
chunkFilename: 'assets/css/[name].css',
}),
];
if (env.ANALYZE_BUNDLE) { plugins.push(new BundleAnalyzerPlugin()); }
return {
entry: './src/index.ts',
mode: 'production',
devtool: 'source-map',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'design-system.js',
library: {
name: 'design-system',
type: 'umd',
},
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.ts?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
transpileOnly: true,
},
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {},
},
'css-loader',
'postcss-loader',
{
loader: 'sass-loader',
options: {},
},
],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
plugins,
resolve: {
alias: {
'#': path.resolve(__dirname, 'src'),
},
extensions: [
'.vue',
'.ts',
'.js',
'.css',
'.ttf',
'.otf',
],
},
externals: {
vue: 'Vue',
},
};
};

vue.js not included in javascript bundle from webpack?

I'm trying to bundle up all my libraries and for the most part? It works.
However, Vue is not being included in the bundle (but everything else is). I can't figure out how to include Vue with the bundled JS from webpack.
My webpack.config.js looks like this:
const autoprefixer = require("autoprefixer");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
var path = require("path");
var Vue = require('vue').default;
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
watch: true,
mode: "production",
entry: "./static/myapp/src/js/index.js",
externals: {
moment: "moment",
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
output: {
filename: "[name].[contenthash].js",
path: path.join(__dirname, "static/myapp/dist/js/"),
publicPath: "/static/myapp/dist/js/",
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
},
module: {
rules: [
{
test: /\.(scss)|(css)$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: "css-loader", options: { sourceMap: true } },
{
loader: "postcss-loader",
},
"sass-loader",
],
},
{
test: require.resolve("jquery"),
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
},
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader",
options: {
name: "[name][hash].[ext]",
outputPath: "fonts/",
},
},
],
},
],
},
plugins: [
new BundleAnalyzerPlugin(),
new MiniCssExtractPlugin({
filename: "../css/[name].[contenthash].css",
}),
new CleanWebpackPlugin(),
new HtmlWebPackPlugin({
template: path.join(
__dirname,
"static/myapp/src/html/webpack_bundles.html"
),
filename: path.join(
__dirname,
"templates/myapp/webpack_bundles.html"
),
inject: false,
}),
],
};
In my index.js I have this:
import "../scss/commonground.scss";
import "../css/style.css";
import "bootstrap";
import "select2";
import "vue";
import "bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css";
import "bootstrap-datepicker/dist/js/bootstrap-datepicker.min";
import "select2/dist/css/select2.css";
All the other libraries (bootstrap, select2, bootstrap-datepicker) get bundled up, the CSS gets bundled together nicely, etc.
The bundle getting created (main.<hash>.js) does not include vuejs. How can I get it to?
I can't figure out how to get it to include vuejs. Any thoughts? Or any ideas that stick out? I've ran through numerous tutorials and how-to's, but can't seem to figure out why this isn't working.

Cannot resolve node_modules in webpack

I am setting up a webpack, but I have a problem.
I know that libraries are automatically connected when node_modules is set in modules of resolve.
So I set up the webpack like this(the webpack file is located under the config folder in the root folder.)
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const env = process.env.NODE_ENV;
const isProd = env === "production";
module.exports = {
mode: env,
context: path.resolve(__dirname, '..'),
entry: {
app: './main.js'
},
output: {
filename: !isProd ? `js/[name].js` : 'js/[name].[contenthash:8].js',
path: path.resolve(__dirname, '../dist'),
publicPath: '/',
chunkFilename: !isProd ? `js/[name].js` : 'js/[name].[contenthash:8].js'
},
resolve: {
alias: {
'#': path.resolve(__dirname, '../src'),
vue$: 'vue/dist/vue.runtime.esm-bundler.js'
},
extensions: [
'.mjs',
'.js',
'.jsx',
'.vue',
'.json',
],
modules: [
path.resolve(__dirname, '../src'),
'node_modules',
path.resolve(__dirname, '../node_modules')
],
},
resolveLoader: {
modules: [
'node_modules',
path.resolve(__dirname, '../node_modules')
],
extensions: ['.js', '.json'],
},
module: {
noParse: /^(vue|vue-router|vuex|vuex-router-sync)$/,
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]',
esModule: false
}
}
}
}
]
},
{
test: /\.(sa|sc|c)ss$/,
use: [ isProd ? {
loader: MiniCssExtractPlugin.loader
} : {
loader: 'style-loader',
}
,
{
loader: "css-loader",
options: {
sourceMap: false,
importLoaders: 2
}
},
{
loader: "sass-loader",
options: {
sourceMap: false
}
}],
},
{
enforce: 'pre',
test: /\.(vue|(j|t)sx?)$/,
exclude: [
/node_modules/,
],
use: [
{
loader: 'eslint-loader',
options: {
extensions: [
'.js',
'.jsx',
'.vue'
],
emitWarning: false,
emitError: false,
fix: true,
}
}
]
},
{
test: /\.m?jsx?$/,
use: [
{loader: 'babel-loader'}
]
}
],
},
plugins: [
new VueLoaderPlugin(),
],
}
However, despite of this setting, code cannot find node_modules.
import Vue from 'vue';
import App from "./src/App.vue";
import { router } from "./src/router/index.js";
new Vue({
router,
render: (h) => h(App),
}).$mount("#root");
this prints out error message on the dev server or at build time.
ERROR in ./main.js
Module not found: Error: Can't resolve 'vue' in '/Users/donghokim/study/wecode/vue-setting-playground/brandi-front-setting'
# ./main.js 1:0-22 5:4-7
However, if set the library path directly, it works.
import Vue from './node_modules/vue/dist/vue';
import App from "./src/App.vue";
import { router } from "./src/router/index.js";
new Vue({
router,
render: (h) => h(App),
}).$mount("#root");
How can I automatically connect node_modules?
solved.... vue$: 'vue/dist/vue.runtime.esm-bundler.js' is of vue 3. I found that vue 2 has no vue.runtime.esm-bundler.js file. After changing to vue.runtime.esm.js, webpack build works

Flash of unstyled content with react and scss

After migrating my CSS files to SCSS, I can see FOUC for my layout elements at the first load (After each reloads of page).
I guess it has something to do with my webpack config so I tried to fix the problem by using mini-css-extract-plugin, but I can still see the problem.
Here is the content of my webpack.config.js file:
const HtmlWebPackPlugin = require("html-webpack-plugin");
const path = require('path');
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,{
loader: "css-loader"
}, {
loader: "sass-loader",
}
]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
},
{
test: /(\.(?:le|c)ss)$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: false,
},
},
{
loader: 'less-loader',
options: {
sourceMap: false,
javascriptEnabled: true,
},
}
]
},
{
test: /\.(png|jpe?g|gif)$/,
use: [
{
loader: 'file-loader',
},
]
}
]
},
output: {
publicPath: "/"
},
devServer: {
historyApiFallback: true,
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin(),
new MomentLocalesPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.AggressiveMergingPlugin()
],
resolve: {
alias: {
"#ant-design/icons/lib/dist$": path.resolve(__dirname, "./src/icons.js")
}
}
};
The problem wasn't because of Webpack. It was because of me being stupid :)
I imported the CSS file inside of a child component, so when I reload the page, it first shows the layout without any styles and then loads the child component and gives the layout a proper style. So basically, the only thing I did to fix the problem was to import the style in the layout component.
import '../style.scsc'

ReactJS with Webpack Setup - App Shows A Blank Page

I had a different thread here: React Build Tool and Dev Server
to setup React with Webpack. Seems like it is working but I have an issue with having the html page show the code from entry point app.js . I can see the code is in bundle.js. If I modify anything in app.js till the render method e.g enter a typo or something I see an error on console but nothing happens with the render() method. Not matter what I do there is no error and nothing shows but a blank page.
app.js
import React from 'react';
import ReactDOM from 'react-dom';
export default class App extends React.Component {
render() {
return (
ReactDOM.render(<h1>Render me!</h1>,
document.getElementById('app'))
);
}
}
Index.html
<!DOCTYPE html>
<html>
<head>
<!-- Bootstrap, latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src='bundle.js'></script>
</body>
</html>
So if I view page source it just shows just
and not the expected Render me!
And just in case below is my webpack.config
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
bundle: './src/app.js'
},
output: {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js'
},
module: {
loaders: [{
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-1']
}
}]
},
resolve: {
extensions: ['*', '.js', '.jsx']
}
};
Also this is from my package.json. I believe my bundle.js is being served from memory right now.
"scripts": {
"start": "webpack-dev-server --port 3000 --hot --inline",
"build": "webpack --progress --colors"
}
I run npm start to compile and start the server. I was expecting npm build will build to dist folder but it doesn't . For now I just want this working one way or the other so I can start coding.
And .babelrc
{
"presets":[
"es2017", "react"
]
}
You are using WebPack 3.x?
Try this config:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PreloadWebpackPlugin = require('preload-webpack-plugin');
const autoprefixer = require('autoprefixer');
const staticSourcePath = path.join(__dirname, 'static');
const sourcePath = path.join(__dirname);
const buildPath = path.join(__dirname, 'dist');
module.exports = {
devtool: 'source-map',
devServer: {
historyApiFallback: true,
contentBase: './'
},
entry: {
"index" :path.resolve(sourcePath, 'index.js')
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].[chunkhash].js',
publicPath: '/'
},
resolve: {
extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx'],
modules: [
sourcePath,
path.resolve(__dirname, 'node_modules')
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.[chunkhash].js',
minChunks: Infinity
}),
new webpack.LoaderOptionsPlugin({
options: {
postcss: [
autoprefixer({
browsers: [
'last 3 version',
'ie >= 10'
]
})
],
context: staticSourcePath
}
}),
new webpack.HashedModuleIdsPlugin(),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'index.html'),
path: buildPath,
excludeChunks: ['base'],
filename: 'index.html',
minify: {
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
removeComments: true,
removeRedundantAttributes: true
}
}),
new PreloadWebpackPlugin({
rel: 'preload',
as: 'script',
include: 'all',
fileBlacklist: [/\.(css|map)$/, /base?.+/]
}),
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env', 'react'],
}
},
include: sourcePath
},
{
test: /\.css$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{ loader: 'css-loader', options: { minimize: true } },
'postcss-loader',
'sass-loader'
]
})
},
{
test: /\.(eot?.+|svg?.+|ttf?.+|otf?.+|woff?.+|woff2?.+)$/,
use: 'file-loader?name=assets/[name]-[hash].[ext]'
},
{
test: /\.(png|gif|jpg|svg)$/,
use: [
'url-loader?limit=20480&name=assets/[name]-[hash].[ext]'
],
include: staticSourcePath
}
]
}
};

Categories