webpack change path script - javascript

Recently, I managed to use ejs-loader with Webpack 4. But, I started to get trouble with the script tag that webpack create into index.html when it launch : <script type="text/javascript" src="main.js"></script>. His src is not right because if we look my build I need src="/dist/main.js" :
node_modules/
dist/
index.html
main.js
publics/
src/
views/
server.js
package.json
webpack.config.js
What I need to add into my webpack.congfig.js to create a src like I want ?
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'source-map',
module: {
rules: [{
test: /\.ejs$/,
use: ['ejs-loader']
}]
},
plugins: [
new HtmlWebpackPlugin({
template: './views/pages/index.ejs'})
]
}

const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'source-map',
output: {
publicPath: '/dist/' // <---- this
},
module: {
rules: [{
test: /\.ejs$/,
use: ['ejs-loader']
}]
},
plugins: [
new HtmlWebpackPlugin({
template: './views/pages/index.ejs'})
]
}

Related

webpack: inject javascript hashed file name in pug template

I'm using pug as my Node.JS view engine.
And I'm bundling my javascript files using webpack with hashname for cache busting.
The problem here is that I don't know how to include the bundled javascript file name in my pug template because every time it generates a new hash name.
How can I get the hash name generated from webpack and include it in my pug file?
This is how it should include the script file:
doctype html
html
include _head
body
script(src='/_bundle/main.649c4c4e6c8076189257.js')
My webpack.config.js
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode: "production",
entry: "./src/_public/js/index.js",
output: {
filename: "main.[contenthash].js",
path: path.resolve(__dirname, "src/_public/_bundle"),
},
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader", "css-loader", "sass-loader",
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
filetype: "pug",
}),
new HtmlWebpackPlugin({
filename: "./src/views/base.pug",
}),
],
}
Configure HtmlWebpackPlugin and HtmlWebpackPugPlugin properly:
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const HtmlWebpackPugPlugin = require('html-webpack-pug-plugin');
module.exports = {
mode: "production",
entry: "./src/_public/js/index.js",
output: {
filename: "main.[contenthash].js",
path: path.resolve(__dirname, "src/_public/_bundle"),
},
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader", "css-loader", "sass-loader",
],
},
],
},
plugins: [
new HtmlWebpackPugPlugin(),
new HtmlWebpackPlugin({
template: './src/views/base.pug',
filename: 'layout.pug',
}),
],
}
Install npm i HtmlWebpackPugPlugin. You will find the js and css references in the layout.pug file.
Actual solution for 2022.
Install the pug-plugin:
npm i -D pug-plugin
Using the pug-plugin:
the Webpack entry-point is the Pug file
all source scripts (JS/TS) can be loaded via require() in Pug
all source styles (CSS/SCSS) can be loaded via require() in Pug
Webpack config for Pug + JS + SCSS:
const path = require('path');
const PugPlugin = require('pug-plugin');
module.exports = {
output: {
path: path.join(__dirname, 'dist/'),
filename: 'js/[name].[contenthash:8].js' // output hashed filename of JS
},
entry: {
// define Pug files in entry:
index: './src/views/index.pug', // => index.html
about: './src/views/about/index.pug' // => about.html
// ...
},
plugins: [
// enable using Pug files as entry point
new PugPlugin({
extractCss: {
filename: 'css/[name].[contenthash:8].css' // output hashed filename of CSS
},
})
],
module: {
rules: [
{
test: /\.pug$/,
loader: PugPlugin.loader, // the Pug loader
},
{
test: /\.(css|sass|scss)$/,
use: ['css-loader', 'sass-loader']
},
],
},
};
Pug file ./src/views/index.pug:
doctype html
html
head
//- load source styles via require()
link(href=require('./path/to/scss/styles.scss') rel='stylesheet')
body
h1 Hello Pug!
//- load source scripts via require()
script(src=require('./path/to/js/index.js'))
Generated HTML:
<html>
<head>
<link href="/css/styles.f57966f4.css" rel="stylesheet">
</head>
<body>
<h1>Hello Pug!</h1>
<script src="/js/index.b855d8f4.js"></script>
</body>
</html>

Script Path for CSS and Bundle is a bit off after WebPack Creates index.html

For some reason, webpack is trying to append client to the href of the script tags for my CSS and bundle. The problem with this is that it's wrong. And I don't know how to tell it to trim that part off.
Before moving to webpack, here is how it looks in production when I was building it with Gulp:
notice above how everything was rooted from within the client folder. You don't even see the client folder because I think expressJS said to start from that point so you only see the root of what's in client such as lib, scripts, etc.
here's what the dist directory looked like when I was using Gulp for that:
Here's how I'm serving my static assets. My ExpressJS server sets the root folder for static asses as dist/client. This has always been the case even when I was using Gulp:
.use(
express.static('dist/client', {
maxage: oneYear,
})
)
Forward to now: It's using my new webpack.config now
Here is a Screenshot of dist from IDE as it is now after using webpack:
But now the index.html is gened by webpack:
<!doctype html><html lang="en"><head><title>My Title</title><meta charset="utf-8"><link href="https://ink.global.ssl.fastly.net/3.1.10/css/ink.min.css"><script src="https://ink.global.ssl.fastly.net/3.1.10/js/ink-all.min.js"></script><script src="https://ink.global.ssl.fastly.net/3.1.10/js/autoload.js"></script><link href="../client/lib/assets/css/main.c09764908684c2f56919.css?c09764908684c2f56919" rel="stylesheet"></head><body><div id="app"></div><script src="../client/scripts/app.c09764908684c2f56919.bundle.js?c09764908684c2f56919"></script></body></html>
webpack.config.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const isProduction = process.env.NODE_ENV === 'production';
const html = () => {
return new HtmlWebPackPlugin({
template: './src/client/index.html',
filename: './client/index.html',
hash: true,
});
};
const copyAllOtherDistFiles = () => {
return new CopyPlugin({
patterns: [
{ from: 'src/client/assets', to: 'client/lib/assets' },
{ from: 'src/server.js', to: './' },
{ from: 'src/api.js', to: './' },
{ from: 'package.json', to: './' },
{ from: 'ext', to: 'client/lib' },
{ from: 'feed.xml', to: 'client' },
{
from: 'src/shared',
to: './shared',
globOptions: {
ignore: ['**/*supressed.json'],
},
},
],
});
};
module.exports = {
entry: './src/client/index.js',
output: {
filename: 'client/scripts/app.[hash].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
target: 'web',
devServer: {
writeToDisk: true,
},
devtool: 'source-map',
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true,
},
},
},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
},
],
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['url-loader'],
},
],
},
plugins: isProduction
? [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: isProduction
? 'client/lib/assets/css/main.[hash].css'
: 'main.css',
}),
html(),
copyAllOtherDistFiles(),
]
: [new CleanWebpackPlugin(), html(), copyAllOtherDistFiles()],
};
Notice for my bundle the src generated includes ../client/ and same for my href for the CSS script.
The problem with this is that my app is served from the root of the client folder in dist. You'd think that ../client/ or ./client/ or client/ would work but it doesn't. When I run the site I get this because it can't find the bundle:
As you can see below, everything it stemming from context of the client folder already in the browser:
(what's also odd about this after moving to webpack, is why do I see a client folder if I told ExpressJS to start from the client folder already? When I was using the same exact code with Gulp, I did not see a client folder because I was already in it from the context of the browser)
So when I change the generated index.html manually in my dist folder, just to see if I can fix it, it all resolves just fine (notice I changed it to just lib/ and scripts/):
</script><link href="lib/assets/css/main.c09764908684c2f56919.css?c09764908684c2f56919" rel="stylesheet"></head><body><div id="app"></div><script src="scripts/app.c09764908684c2f56919.bundle.js?c09764908684c2f56919"></script></body></html>
The problem is I don't know how to get webpack to strip out that ..client/ part of the url when it gens the index.html. I've tried adding a publicPath property with '/', or './' or '' but no luck so far.
In other words this does not load: http://localhost:8080/client/scripts/app.b4b3659d9f8b3681c26d.bundle.js
but this does:
http://localhost:8080/scripts/app.b4b3659d9f8b3681c26d.bundle.js
http://localhost:8080/lib/assets/css/main.b4b3659d9f8b3681c26d.css
I think as long as you just write your output assets to same folder with the public folder set at your server, then it would work. Assuming the client will still be the public:
.use(
express.static('dist/client', {
maxage: oneYear,
})
)
I suggest to set entire output as client dir along side with its publicPath in webpack config for client:
output: {
filename: 'scripts/app.[hash].bundle.js',
path: path.resolve(__dirname, 'dist/client'),
publicPath: '/'
}
with the setting above, we don't have to specify the folder the html template location:
new HtmlWebPackPlugin({
template: path.resolve(__dirname, 'src/client', 'index.html'),
filename: 'index.html',
hash: true,
});
I don't quite understand yet why this fixed it but here is what made it work.
Definitely didn't need the publicPath:
output: {
filename: 'scripts/app.[hash].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
Changed my static path to be:
.use(
express.static('dist', {
maxage: oneYear,
})
)
move index.html out of the client folder and into the root of dist:
return new HtmlWebPackPlugin({
template: path.resolve(__dirname, 'src/client', 'index.html'),
filename: 'index.html',
hash: true,
});
Same with my bundle
output: {
filename: 'scripts/app.[hash].bundle.js',
publicPath: '/',
path: path.resolve(__dirname, 'dist'),
},
Same with assets:
patterns: [
{ from: 'src/client/assets', to: 'lib/assets' },
I don't see what moving it to the root of dist makes any difference but for some reason rendering / requesting to process index.html from the root of dist instead of dist/client works`

How to exclude directory from getting bundled by Webpack?

Expected:
When I build with webpack, all my JS files get bundled except for the files in the ./src/Portfolio directory as per my Webpack.config.js settings.
Actual:
Webpack bundles all the files including the ones in the directory despite the settings and other variations i have provided within webpack.config.js.
Code:
Webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
devtool: 'source-map',
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: [
path.resolve(__dirname, './src/Portfolio/')
]
}
]
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
}
};
Output:
How can i successfully exclude the ./src/Portfolio directory and its
contents?
Depending on what your folder structure looks like it appears you aren't providing it the right directory location to exclude. I would think something like this should work, but if not please share your folder structure.
const path = require('path');
module.exports = {
entry: './src/index.js',
devtool: 'source-map',
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: [
'./src/Portfolio/'
]
}
]
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
}
};
I know the op is using javascript, fyi a similar problem can occur using typescript with webpack.
In this case excluded directories can be added to tsconfig.json instead of webpack.config.js,
//tsconfig.json
{
"compilerOptions": {
...
},
"exclude": [
"./src/Portfolio/",
]
}

React & Webpack: Loading failed for the <script> with source http://localhost:8080/app/bundle.js

I am new in reactjs. I tried to configure react with basic index page including index.js(containing a console.log()) but when i tried to run server index.html showing properly but bundle.js is not loading. I search it a lot but not getting proper answer can any one help me please.
my webpack.config.js is
// Webpack config js.
var webpack = require("webpack");
var path = require("path");
var DIST_VAR = path.resolve(__dirname, "dist");
var SRC_VAR = path.resolve(__dirname, "src");
var config = {
entry : SRC_VAR + "\\app\\index.js",
output: {
path: DIST_VAR + "\\app\\",
filename: "bundle.js",
publicPath : "\\app\\",
},
module: {
rules: [
{
test: /\.js?/,
include: SRC_VAR,
loader: "babel-loader",
query: {
presets: [ "react" , "es2015" , "stage-2"]
}
}
]
}
};
module.exports = config;
Error is showing in console: Loading failed for the with source “http://localhost:8080/app/bundle.js”.
Edit:
Folder Listing added..
Folder PATH listing
Volume serial number is BE9C-4E51
C:.
| package-lock.json
| package.json
| webpack.config.js
|
+---dist
| | index.html
| |
| \---app
| bundle.js
|
+---node_modules
| <Here the node_modules>
\---src
| index.html
|
\---App
index.js
I'll make some assumptions without seeing your project folder structure.
Looks like it could be your publicPath. Unless that's what you intended, the /app folder shouldn't be visible and since your console is showing "localhost:8080/app/bundle.js" that means it's looking for "project-root/src/app/app/bundle.js" instead of "project-root/src/app/bundle.js"
In the webpack docs they're telling you to default to root '/' and looking at my own webpack file thats what mine is currently set to as well.
Reference:
https://webpack.js.org/guides/public-path/
Edit: Here's an example using Webpack 3. Version 4 just came out and this will not work, so I'd be careful where you're getting your config examples from if you are using Webpack 4.
const webpack = require('webpack');
const path = require('path');
module.exports = {
plugins: [
// new webpack.NamedModulesPlugin(),
// new webpack.HotModuleReplacementPlugin()
],
context: path.join(__dirname, 'src'),
entry: [
// 'webpack/hot/dev-server',
// 'webpack-hot-middleware/client',
// 'babel-polyfill',
// 'history',
'./index.js'
],
output: {
path: path.join(__dirname, 'www'),
filename: 'bundle.js',
publicPath: '/'
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loaders: ['react-hot-loader/webpack', 'babel-loader']
}],
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
],
},
};
after installing
npm init -y
and
npm install --save-dev webpack webpack-dev-server webpack-cli
and your structure files
src/
build/
webpack.config.js
package.json
go to package.json, and add build command:
"scripts": {
"start":"webpack serve --mode development",
"build":"webpack"
},
in webpack.config.js
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, './src/index.js'),
output: {
path: path.resolve(__dirname, './build'),
filename: 'bundle.js',
},
devServer: {
contentBase: path.resolve(__dirname, './build'),
},
};
so,in your build/index.html
<script type="text/javascript" src="./bundle.js"></script>

Watch all Less Files but only compile one main one

So I downloaded a theme that has a bunch of less files but there is a main one that imports the others in the correct order. It came with a gulp file that watches any .less file but recompiles only the one that imports all the others. It looks like so:
gulp.task('less', function () {
return gulp.src(Paths.LESS_TOOLKIT_SOURCES)
.pipe(sourcemaps.init())
.pipe(less())
.pipe(autoprefixer())
.pipe(sourcemaps.write(Paths.HERE))
.pipe(gulp.dest('dist'))
})
My webpackconfig so far looks like the following:
// Things I still need to do:
// 1) Add uglifier plugin for minification
var path = require('path');
var webpack = require('webpack');
var cssnext = require('cssnext');
var cssimport = require('postcss-import');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var isProd = process.env.NODE_ENV === 'production' ? true : false;
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./app/index'
],
stylePath: path.resolve(__dirname, 'app', 'style'),
postcss: function () {
return [
cssimport({
path: './app/style/index.css',
onImport: function (files) {
files.forEach(this.addDependency)
}.bind(this)
}),
cssnext()
]
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
cssFilename: 'style.css',
publicPath: '/static/'
},
plugins: [
new ExtractTextPlugin('style.css', {
allChunks: true
}),
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'app')
},
{
test: /\.css$/,
loader: isProd ? ExtractTextPlugin.extract('style', 'css? modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss') : 'style!css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss'
},
{
test: /\.less$/,
loader: "style!css!less"
}]
},
resolve: {
root: path.resolve(__dirname),
extensions: [
'',
'.js',
'.css'
],
modulesDirectories: [
'app',
'node_modules'
]
}
};
I am trying to accomplish the the same thing but with webpack. I have installed and setup the less-loader like the guide says but it tries to compile all of the files. Is there a way to set it up like the gulp file that will watch any file but only compile a specific file? I have this working in brunch when working in Phoenix but I trying to switch brunch out with webpack for phoenix.
In brunch I just told it to ignore the folder with the less files and then had the main less file outside that directory so brunch would only compile the main less file and import the others.

Categories