hot reload pug with webpack - node.js

I created a web application and i'm generating my index.html with a pug file.
The pug template needs to get data from a json file, and so far I managed to inject the data with both pug-loader and pug-html-loader.
The problem comes when I run the application with hot-reloading (using webpack-hot-middleware). the application dosen't reload when I change the json file, which is really annoying because any other file change triggers a reload, and I don't want to restart the application manually everytime I change the json file.
this is my webpack configuration:
{
context: '/src',
entry: 'index.js',
output: {
filename: 'index.js',
path: '/dist'
},
resolve: {
extensions: ['.js', '.vue', '.scss', 'json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': config.pwd,
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: [
'style-loader',
'css-loader',
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: ['./src/variables.scss', './src/mixins.scss']
}
}
]
}
}
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: ['./src/variables.scss', './src/mixins.scss']
}
}
]
},
{
test: /\.pug$/,
use: [
{
loader: 'pug-loader',
options: {}
}
]
}
]
},
{
[
new HtmlWebpackPlugin({
template: 'index.pug',
inject: true,
data: require('./pug.json')
})
]
}
}
does any one know how i can make a change in pug.json trigger a hot reload?

Related

Programmatic Webpack & Jest (ESM): can't resolve module without '.js' file extension

I'm using webpack programmatically, with typescript, ESM, and jest. In a jest test I'm getting errors for not including a .js file extension when importing ES modules. For example:
Module not found: Error: Can't resolve 'modulename' in '/path/components'
Did you mean 'modulename.js'?
BREAKING CHANGE: The request 'modulename' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
The module in question does indeed have "type": "module" set in its package.json. I have tried adding .js to the import, and it doesn't help.
I'm invoking jest with:
node --experimental-vm-modules --experimental-specifier-resolution=node node_modules/jest/bin/jest.js
as is recommended in the docs (everything else works except webpack). Note that I have tried with and without --experimental-specifier-resolution=node (this has helped in other similar circumstances).
Any thoughts on how to get webpack to work? Thanks in advance!
Note: everything was working until it was all converted to ESM! Now only programmatic webpack isn't working.
Webpack config:
{
entry,
target: 'web',
output: {
path: outputDir,
filename: '[name].js',
},
mode: process.env.NODE_ENV as 'development' | 'production' | 'none' | undefined,
resolve: {
extensions: [
'.ts',
'.tsx',
'.js',
'.jsx',
'.ttf',
'.eot',
'.otf',
'.svg',
'.png',
'.woff',
'.woff2',
'.css',
'.scss',
'.sass',
],
},
module: {
rules: [
{
test: /\.(ttf|eot|otf|svg|png)$/,
loader: 'file-loader',
},
{
test: /\.(woff|woff2)$/,
loader: 'url-loader',
},
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
sourceType: 'unambiguous',
presets: [
[
'#babel/preset-env',
{
corejs: '3.0.0,',
useBuiltIns: 'usage',
},
],
'#babel/preset-react',
'#babel/preset-typescript',
],
plugins: [
'css-modules-transform',
[
'babel-plugin-react-scoped-css',
{
include: '.scoped.(sa|sc|c)ss$',
},
],
'#babel/plugin-proposal-class-properties',
],
},
},
{
test: /\.(sc|c|sa)ss$/,
use: [
'style-loader',
'css-loader',
'scoped-css-loader',
'sass-loader',
],
},
],
},
}
Ok so I found the solution here.
Basically, had to add 2 things to the webpack config under module.rules:
{
test: /\.m?js/,
type: "javascript/auto",
},
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
#nerdlinger answer worked for me. I had this webpack.config.js
module.exports = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.(js)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
],
}
...
}
and i changed it to this
module.exports = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.(js)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
},
resolve: {
fullySpecified: false,
}
}
],
}
...
}

webpack relative url in css, creating copied export svg files

I have the below webpack.config. I'm trying to use relative url in my style.css to point to some svg files. The problem is the relative url is referencing a copy of the svg file which is just an export statement. Does anyone know why my webpack.config is creating these copied svg files? The files aren't working to show the image but the original svg does, so just trying to get webpack to stop creating the copied export file and just reference the actual svg. Thanks.
webpack.config.cs:
const path = require('path');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { VueLoaderPlugin } = require("vue-loader");
const srcPath = path.resolve(__dirname, './src');
const stylePath = path.resolve(srcPath, './styles');
const bldPath = path.resolve('../SpeedRunApp/wwwroot/dist');
module.exports = {
devtool: 'source-map',
entry: {
master: path.resolve(srcPath, 'index.js'),
style: `${stylePath}/style.css`
},
mode: 'development',
watch: true,
module: {
rules: [
{
test: /\.scss$/,
use: [{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [ require('autoprefixer') ]
}
}
},
{ loader: 'sass-loader' }]
},
{
exclude: /(node_modules|bower_components)/,
include: srcPath,
test: /\.js$/,
use: [{ loader: 'babel-loader' }]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
publicPath: './fonts/',
outputPath: './fonts/',
esModule: false
}
}
]
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: './images/',
publicPath: './images/',
esModule: false
}
}
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
chunks: 'all',
name: 'vendor',
test: /[\\/]node_modules[\\/]/
}
}
},
},
output: {
filename: '[name].min.js',
chunkFilename: '[name].min.js',
globalObject: 'this',
path: `${bldPath}`,
publicPath: '/dist/'
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [`${bldPath}/**`],
dry: false,
verbose: true,
dangerouslyAllowCleanPatternsOutsideProject: true
}),
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: '[name].min.css'
})
]
};
style.css:
.twitter-logo {
background: url(../fonts/Twitter_Logo_WhiteOnBlue.svg)
}
.twitch-logo {
background: url(../fonts/TwitchGlitchPurple.svg)
}
.youtube-logo {
background: url(../fonts/youtube_social_square_red.svg)
}
Weird copy files webpack is creating:
Content of copied files:
I bailed on using the css and just went with importing the svgs, changed code to this and works. I put my own non-fontawesome svgs in the "font" folder in the Node.js project (webpack project) and that is correctly copying them to the static font folder in the Web MCV project.
Index.js
import '#fortawesome/fontawesome-free/js/all.min.js'
import './fonts/TwitchGlitchPurple.svg';
import './fonts/Twitter_Logo_WhiteOnBlue.svg';
import './fonts/youtube_social_square_red.svg';
import './fonts/pie-chart.svg';
Node.js (webpack) project:
Successful copy to static folder in Web.MVC project:
Code using svg:

FLUSH CHUNKS warning occurs with TSX, but not with JS

I get this warning:
[FLUSH CHUNKS]: Unable to find styles/localhost-theme-css in Webpack chunks. Please check usage of Babel plugin.
Following code causes the warning (for the setup of react-universal-component, which does server side rendering with code-splitting which reads only necessary CSS file for the page and domain being read by the user):
export default (props) => {
if (props.site !== undefined) {
import(`../styles/${props.site}/theme.css`);
}
Above code is in Routes.tsx, whole file looks like:
import React from "react"
import universal from "react-universal-component"
import { Switch } from "react-router"
const determineHowToLoad = ({ page }) => {
if (typeof page !== 'string') {
return page();
} else {
return import(`./${page}`);
}
}
const UniversalComponent = universal(determineHowToLoad, {
loadingTransition: false
})
export default (props) => {
if (props.site !== undefined) {
import(`../styles/${props.site}/theme.css`);
}
return (
<div>
Test
</div>
)
}
However, this happens only if when the filename is Routes.tsx. If I change to Routes.js, no warning occurs. Even with the warning and filename being Routes.tsx, all the things looks working well but only warning occurs in console terminal.
My webpack setting:
1. webpack.dev-client.js:
optimization: {
splitChunks: {
chunks: "initial",
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: "vendor"
}
}
}
},
devtool: "source-map",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader"
}
]
},
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: "ts-loader"
}
]
},
{
test: /\.(js|jsx)$/,
use: 'react-hot-loader/webpack',
include: /node_modules/
},
{
test: /\.css$/,
use: [
ExtractCssChunks.loader, "css-loader",
]
},
....
resolve: {
extensions: [".ts", ".tsx", ".js", ".css"]
},
2. webpack.dev-server.js:
devtool: "inline-source-map",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader"
}
]
},
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: "ts-loader"
}
]
},
{
test: /\.css$/,
use: [
ExtractCssChunks.loader, "css-loader"
]
},
....
resolve: {
extensions: [".ts", ".tsx", ".js", ".css"]
},
How can I solve it so that I can use tsx without FLUSH CHUNKS warning?
Try setting the module to "EsNext" in tsconfig.json, I had the similar issue changing to "EsNext" solved it for me.

Webpack 2 - Problems parsing node_module

I'm unit testing with mocha-webpack v1.0.1, node v6.10. However, I'm getting an error from one of our node modules, where webpack couldn't parse a #. This is an internal library that we use that runs fine in another development environment. So, I'm confused why this is happening since you would think that a library in your node_module would be sort of self-sustaining and would know how to parse itself (and is validated as working in another environment).
Error in ./~/abc-components/src/abc-theme/index.scss
Module parse failed: /path/to/app/node_modules/abc-components/src/abc-theme/index.scss Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type.
| #charset "UTF-8";
| #import "abc-variables";
| #import "alert";
I believe # is an alias we use for resolving the module path in that library. I've modeled my setup after this tutorial.
From package.json:
"unit": "BABEL_ENV=test mocha-webpack --webpack-config build/webpack.test.conf.js --require test/unit/.setup src/**/*.spec.js --recursive --watch"
From build/webpack.test.conf.js config, including some comments of things I've tried:
var path = require('path')
var webpack = require('webpack')
var utils = require('./utils')
var config = require('../config')
// var nodeExternals = require('webpack-node-externals');
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
resolve: {
modules: [path.resolve('./src'), "node_modules"],
extensions: ['.js', '.vue', '.json', '.ts'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': resolve('src')
}
},
// externals: [nodeExternals()],
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
// plugins: [
// new webpack.optimize.CommonsChunkPlugin({
// name: "vendor",
// filename: "vendor.js",
// minChunks: function (module) {
// // This prevents stylesheet resources with the .css or .scss extension
// // from being moved from their original chunk to the vendor chunk
// if(module.resource && (/^.*\.(css|scss)$/).test(module.resource)) {
// return false;
// }
// return module.context && module.context.indexOf("node_modules") !== -1;
// }
// }),
// new webpack.DefinePlugin({
// 'process.env': require('../config/test.env')
// })
// ],
module: {
loaders: [
{
test: /\.(js|vue)$/,
// loader: 'eslint-loader',
// enforce: 'pre',
include: [resolve('src'), resolve('test'), resolve('node_modules')],
/* options: {
formatter: require('eslint-friendly-formatter')
} */
},
{
test: /\.pug$/,
loader: 'pug-loader'
},
{
test: /\.vue$/,
loader: 'vue-loader'
// options: vueLoaderConfig
},
{
test: /\.ts$/,
loader: "awesome-typescript-loader",
include: [resolve('src'), resolve('test')]
},
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ['es2015']
},
include: [resolve('src'), resolve('test')]
// exclude: /node_modules/
},
{
test: /\.(mp3|wav)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('audio/[name].[hash:7].[ext]')
}
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
resolveLoader: {
alias: {
// necessary to to make lang="scss" work in test when using vue-loader's ?inject option
// see discussion at https://github.com/vuejs/vue-loader/issues/724
'scss-loader': 'sass-loader'
}
}
}
Include following config in loader.
module: {
loaders: [
{
test: /\.(scss|sass)$/i,
include: [
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, 'path/to/imported/file/dir'), <== This solved the issue
],
loaders: ["css", "sass"]
},
]
},

Webpack suppress eslint warnings on browser console

I`ve finished configuring my eslint rules and refactoring project files according to my rules. Thing is that I have some warnings that I may want to leave there for a while. But my problem is that warnings are being shown on browser console, what makes development impossible.
Below, my webpack config:
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const context = path.resolve('.');
module.exports = {
context: context,
entry: './src/client.js',
output: {
path: path.join(context, 'build/client'),
publicPath: '/static/',
filename: '[name]-[hash].js'
},
module: {
preLoaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader'
},
],
loaders: [{
test: /(?:node_modules).+\.css$/,
loader: 'style!css'
}, {
test: /\.scss$/,
loader: ExtractTextPlugin.extract([
'css-loader',
'postcss-loader',
'sass-loader',
'sass-resources'
])
}, {
test: /\.js$/,
loader: 'babel',
exclude: /(node_modules)/
}, {
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/font-woff"
}, {
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/font-woff"
}, {
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=application/octet-stream"
}, {
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: "file"
}, {
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: "url?limit=10000&mimetype=image/svg+xml"
}, {
test: /\.json$/,
loader: 'json'
}]
},
postcss: function() {
return [
require('autoprefixer')
];
},
sassResources: [
path.resolve(__dirname, '../src/stylesheets/base/_variables.scss'),
path.resolve(__dirname, '../src/stylesheets/base/_mixins.scss')
],
devServer: {
watchOptions: {
aggregateTimeout: 1000
}
},
plugins: [
new ExtractTextPlugin("[name]-[hash].css"),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'local')
})
],
devtool: "cheap-module-source-map"
};
I have no problem with errors being displayed on browser console, but is there a way to suppress warnings ONLY on browser console and not on the node terminal?
https://devhub.io/repos/coryhouse-eslint-loader
In my webpack.config.js I have options setup:
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
['es2015', {modules: false}],
'react'
],
plugins: [ 'react-hot-loader/babel' ]
}
}, {
loader: 'eslint-loader',
options: {
quiet: true
}
}
]
}
]
}
The last line is quiet: true, which is how it suppresses the warnings.
Use
clientLogLevel: "none"
in the devServer config
Doc: https://webpack.js.org/configuration/dev-server/#devserverclientloglevel
devServer.clientLogLevel
string: 'none' | 'info' | 'error' | 'warning'
When using inline mode, the console in your DevTools will show you messages e.g. before reloading, before an error or when Hot Module Replacement is enabled. Defaults to info.
devServer.clientLogLevel may be too verbose, you can turn logging off by setting it to 'none'.
webpack.config.js
module.exports = {
//...
devServer: {
clientLogLevel: 'none'
}
};
Usage via the CLI
webpack-dev-server --client-log-level none

Resources