webpack reload styles without page refresh - javascript

I use webpack and livereload plugin but when I change something in styles, page refresh but I don't want it.
When I use gulp, I change anything in styles and save it and then css reload without page refresh.
Why does not work like gulp on webpack?
Codes are below
webpack.config.js
const path = require("path");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const WebpackNotifierPlugin = require("webpack-notifier");
const webpack = require("webpack");
const LiveReloadPlugin = require("webpack-livereload-plugin");
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const Dotenv = require('dotenv-webpack');
module.exports = {
entry: [
"./resources/js/app.jsx",
"./resources/scss/app.scss",
],
devtool: "source-map",
output: {
path: path.resolve(__dirname, "public/assets"),
filename: "js/app.js",
publicPath: "/public/assets/"
},
module: {
rules: [{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["env", "react", 'stage-2']
}
}
}, {
test: /\.(scss)$/,
loader: ExtractTextPlugin.extract(['css-loader', 'sass-loader', "postcss-loader"])
}]
},
resolve: {
extensions: ["*", ".js", ".jsx"]
},
watch: true,
plugins: [
new CopyWebpackPlugin([{
from: "node_modules/bootstrap/dist",
to: "plugins/bootstrap"
}, , {
from: 'node_modules/font-awesome/css',
to: 'plugins/font-awesome/css',
}, {
from: 'node_modules/font-awesome/fonts',
to: 'plugins/font-awesome/fonts',
}]),
new WebpackNotifierPlugin({
alwaysNotify: true
}),
new webpack.LoaderOptionsPlugin({
debug: true
}),
new LiveReloadPlugin(),
new ExtractTextPlugin({
filename: 'css/app.css'
}),
new Dotenv({
path: './.env',
safe: true
}),
new webpack.EnvironmentPlugin(['NODE_ENV'])
],
node: {
fs: "empty"
}
};
package.json
"scripts": {
"start": "webpack-dev-server --history-api-fallback --progress --colors",
"dev": "cross-env NODE_ENV=development webpack --progress --color",
"prod": "cross-env NODE_ENV=production webpack -p --progress --color"
},
I use "npm run dev" command.
Where is the problem ?

ExtractTextPlugin sadly doesn't support hot module replacement.
From the page plugin description:
No Hot Module Replacement
what you need to do is use the plugin just in production.
rules: [
...
{
test: /\.scss$/,
use: process.env.NODE_ENV === 'production' ?
ExtractTextPlugin.extract([
"css-loader", "sass-loader", "postcss-loader"
]) : [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader" },
{ loader: "postcss-loader" }
]
}
]

Try like this it will work.
{
test: /\.(s*)css$/,
loader: ExtractTextPlugin.extract(['style-loader', 'css-loader', "sass-loader"])
}
If you share the package.json than it will be helpful for others to solve the issue.

Related

Webpack5 is unable to compile images while is running and raise an error

I am using webpack5 config to run a react repository and everything seems to be working fine except loading images, I have an error that I do not understand:
ERROR in ./src/assets/styles/main.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleNotFoundError: Module not found: Error: Can't resolve 'file-loader' in '/Users/user.user/Desktop/react-boilerplate-master'
I have tried to reinstall the mini-css-extract-plugin butt didn't worked, not sure what could be the problem here.
This is the webpack config:
const webpack = require('webpack');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const {
NODE_ENV: nodeEnv = 'development'
} = process.env;
const devMode = nodeEnv !== "production";
const pkg = require("./package.json");
module.exports = {
entry: {
app: "./src/index.js",
vendor: Object.keys(pkg.dependencies)
},
output: {
filename: devMode ? "[name].js" : "[name].[hash].js",
path: path.resolve(__dirname, "dist"),
chunkFilename: devMode ? "[name].js" : "[name].[chunkhash].js",
publicPath: "/"
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
chunks: "all"
}
}
}
},
devServer: {
historyApiFallback: {
index: "/index.html",
port: 3001
}
},
watchOptions: {
poll: true
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]?[contenthash]',
outputPath: 'images/',
},
},
],
},
{
test: /\.(woff(2)?|ttf|eot|otf|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: "fonts/",
},
},
],
},
{
test: /\.scss|css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: { url: false }
},
{
loader: "sass-loader",
options: {
sassOptions: {
includePaths: ["src/styles/"]
}
}
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: devMode ? "[name].css" : "[name].[hash].css",
chunkFilename: devMode ? "[id].css" : "[id].[hash].css"
}),
new HtmlWebpackPlugin({
filename: "index.html",
chunks: ["vendor", "app"],
template: path.join(__dirname, "public", "index.html")
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(nodeEnv),
'process.env.API_PATH': JSON.stringify(process.env.API_PATH)
})
]
};
and the package.json scripts:
``` "scripts": {
"start": "./node_modules/webpack/bin/webpack.js --mode development",
"build": "./node_modules/webpack/bin/webpack.js --mode production",
"start:watch": "./node_modules/webpack/bin/webpack.js --mode development --watch",
"dev": "webpack serve --mode development --open",
"test": "./node_modules/jest/bin/jest.js --env=jsdom",
"test:watch": "./node_modules/jest/bin/jest.js --watch --env=jsdom --verbose",
"test:watch:log": "TERM=dumb ./node_modules/jest/bin/jest.js --watch --env=jsdom --verbose",
"coverage": "npm test -- --coverage",
"eslint": "eslint ./src",
"profile": "./node_modules/webpack/bin/webpack.js --profile --json > stats.json",
"profile:analyze": "./node_modules/.bin/webpack-bundle-analyzer ./stats.json"
},```
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/AZH7s.png
Looks like I can reproduce your issue with the above setup. It's very likely an issue from using file-loader in webpack 5.
Basically webpack has urged to use asset module in favor of kind of traditional loader like file-loader.
In short, it should be working if you replace the file-loader with asset module like:
{
test: /\.(png|jpg|gif|svg)$/,
type: 'asset/resource',
// use: [
// {
// loader: 'file-loader',
// options: {
// name: '[path][name].[ext]?[contenthash]',
// // outputPath: 'images/',
// },
// },
// ],
},

Heroku throws 403 forbidden after build with webpack

I have a problem with building my vuejs app on heroku after using my webpack config instead of simple using vue-cli-service build
package.json
"build": "webpack --config webpack.config.js",
//before webpack I use this
//"build": "vue-cli-service build",
after build with webpack my heroku build the whole app properly and I have this:
remote: -----> Compressing...
remote: Done: 92.6M
remote: -----> Launching...
remote: Released v69
remote: https://someapp.herokuapp.com/ deployed to Heroku
but when i go to https://someapp.herokuapp.com/, my app is blank and I have 403 Forbidden nginx :/
I do not know what is wrong with my webpack :/
here is my webpack config
webpack.config.js
var path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
entry: './src/main.js',
mode: 'production',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'someapp.bundle.js'
},
optimization: {
usedExports: true,
minimize: true,
minimizer: [new UglifyJsPlugin()],
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: 'someapp.bundle.css'
}),
new OptimizeCSSAssetsPlugin(),
new CompressionPlugin({
test: /\.js(\?.*)?$/i,
algorithm: "gzip",
filename: "[path][base].gz"
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},{
test: /\.vue$/,
loader: 'vue-loader'
},{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
},{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader?name=./img/[name].[ext]'
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader?name=./img/[name].[ext]'
}, {
test: /\.jpg$/,
use: ["file-loader?name=./img/[name].[ext]"]
}, {
test: /\.png$/,
use: ["file-loader?name=./img/[name].[ext]"]
}]
},
resolve: {
alias: {
'#': path.resolve('src')
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: false
}
#EDIT:
I change build to vue-cli-service build and whole app was created successfully and a I do not have 403:Forbidden, so, problem must be with webpack
can someone tell me what is wrong with my heroku build?
thanks for any help!

Why PWA can be installed only in dev mode?

I'm trying to integrate PWA in my react project, when i run using webpack-dev-server i can see the PWA app that i can install in my computer, but when i build the project with webpack and try to run it, i can't do it anymore
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const { styles } = require("#ckeditor/ckeditor5-dev-utils");
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const BUILD_DIR = path.resolve(__dirname, "public");
const APP_DIR = path.resolve(__dirname, "src");
const envs = require('./config/envs').getEnv;
const plugins = require('./webpack-plugins');
module.exports = (env) => {
console.log("OUTPUT: env", env)
const config = envs(env.NODE_ENV);
const mode = env.production ? 'production' : 'development';
return {
mode,
entry: `${APP_DIR}/index.js`,
output: {
filename: "js/bundle.js",
path: BUILD_DIR,
publicPath: "/"
},
node: {
net: "empty",
tls: "empty",
dns: "empty",
fs: "empty"
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
exclude: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
"babel-loader",
{
loader: "eslint-loader",
options: {
failOnError: true,
emitError: true,
emitWarning: true
}
}
]
},
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: "graphql-tag/loader"
},
{
test: /\.(jpg|png|gif|svg|pdf|ico)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name]-[hash:8].[ext]"
}
}
],
exclude: [
/\.(js|jsx|mjs)$/,
/\.html$/,
/\.json$/,
/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
/ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/
]
},
{
test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
use: ["raw-loader"]
},
{
test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
use: [
{
loader: "style-loader",
options: {
singleton: true
}
},
{
loader: "postcss-loader",
options: styles.getPostCssConfig({
themeImporter: {
themePath: require.resolve("#ckeditor/ckeditor5-theme-lark")
},
minify: true
})
}
]
}
]
},
devServer: {
historyApiFallback: true,
watchContentBase: true,
contentBase: "./public"
},
resolve: {
extensions: [".js"],
alias: {
src: path.resolve(__dirname, "src"),
shared: path.resolve(__dirname, "src", "shared"),
config: path.resolve(__dirname, "config"),
screens: path.resolve(__dirname, "src", "screens"),
package: path.resolve(__dirname, "package.json")
}
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new MomentLocalesPlugin({
localesToKeep: ['es-us', 'fr', 'es'],
}),
new webpack.DefinePlugin({
CONFIG: JSON.stringify(config),
}),
plugins.manifest,
plugins.sw
]
}
};
the Scripts on package.json
"build:local": "webpack --env.NODE_ENV=local --env.production --progress",
"start": "node server.js",
"dev": "webpack-dev-server --inline --watch --host 0.0.0.0 --env.NODE_ENV=local --env.development --progress"
Webpack packages used :
"webpack": "4.19.1",
"webpack-cli": "^2.0.15",
"webpack-dev-server": "^3.1.3",
"webpack-manifest-plugin": "^2.2.0"
PS: I tried both --env.production and --env.development in the build but neither worked
Any lead would be appreciated !
Making the app HTTPS fixed it, many thanks #Mathias

keep folder structure of source files in webpack

I have one .html page(index.html) and one entry point(index.js) and I want that dist folder keeps folder structure of my source files.
./webpack.config.js
./src/index/index.html
./src/index/index.js
./src/index/script1.js
./src/index/style1.scss
./src/assets/imgs/bg.jpg
I manage to write a webpack config file that works as I want but only when I use 'npm run build' and webpack give me a final build version.'
if I use 'npm run dev' then dev server opens a page that shows directories list.
How can I solve my problem?
this is my webpack.config.js
const webpack = require("webpack");
const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
optimization: {
minimize: false
},
entry: {'index': './src/index/index.js'},
output: {
filename: '[name]/[name].js',
path: path.resolve(__dirname, './dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development',
reloadAll: true,
},
},
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development',
reloadAll: true,
},
},
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.html$/,
exclude: /node_modules/,
use: [
{
loader: 'html-loader',
options: {
minimize: false,
publicPath: './'
}
}
]
},
{
test: /\.(png|jpg|jpeg)$/,
exclude: /node_modules/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/imgs/',
publicPath: '../assets/imgs/'
}
}
]
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name]/[name].css",
chunkFilename: '[id].css',
ignoreOrder: false
}),
new HtmlWebpackPlugin({
filename: 'index/index.html',
inject: true,
chunks: ['index'],
template: './src/index/index.html'
}),
new CleanWebpackPlugin()
]
};
package.json :
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
}
I want dist folder to be like this :
./dist/index/index.html
./dist/index/index.js --> final .js bundle
./dist/index/index.css --> final .css bundle
./dist/assets/imgs/bg.jpg

Webpack HotModuleReplacementPlugin not updating page when changes to files are made

The page loads up correctly and even logs to client console [WDS] Hot module replacement enabled. But when I make changes to files nothing is reflected on the page. Even on reload. Only when restarting the server.
Not sure if this matter but Im using redux.
webpack.config.js
var precss = require('precss');
var autoprefixer = require('autoprefixer');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'eval-source-map',
entry: __dirname + '/src/index.js',
output: {
path: __dirname + '/build',
filename: 'bundle.js',
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel'
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.css$/,
loader: 'style!css?modules!postcss'
},
{
test: /\.(png|jpg|jpeg|gif|woff)$/,
loader: 'url-loader?limit=8192'
}
]
},
postcss: function() {
return [autoprefixer, precss];
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + '/src/index.html'
}),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './public',
colors: true,
historyApiFallback: true,
inline: true,
hot: true
},
jest: {
moduleFileExtensions: ["js", "jsx"]
}
};
.babelrc
{
"presets": ["react", "es2015", "stage-0"],
"env": {
"development": {
"plugins": [["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
// this is important for Webpack HMR:
"locals": ["module"]
}]
// note: you can put more transforms into array
// this is just one of them!
}]]
}
}
}
Try adding
"scripts": {
"start": "node_modules/.bin/webpack-dev-server --progress --inline"
},
in your package.json file, and use npm start.
adding additional entry point in webpack config will reload the page automatically, however you will loose all the state because of a refresh.
entry: [
'webpack-hot-middleware/client?reload=true',
__dirname + '/src/index.js',
],
and in server js
app.use(require('webpack-hot-middleware')(compiler));

Categories