I arranged assets paths in my webpack project, it works well under webpack-dev-server, but publishing the project(using Github pages); it seems the browser can't reach assets because its absolute path
for example,
I have src/components/banner.html as bellow
<div class="c-banner ">
<h3 class="c-banner__title">banner header</h3>
<p class="c-banner__desc">
banner body
</p>
more
<i class="c-icon c-icon--flag c-banner__icon"></i>
<i class="c-icon c-icon--cancel-circle c-banner__close js-banner__close"></i>
<img src="../assets/images/profile.png" alt="">
</div>
it bundled in dist/components/banner.html as bellow
<head><link href="/assets/css/styles.css" rel="stylesheet"></head>
<div class="c-banner ">
<h3 class="c-banner__title">banner header</h3>
<p class="c-banner__desc">
banner body
</p>
more
<i class="c-icon c-icon--flag c-banner__icon"></i>
<i class="c-icon c-icon--cancel-circle c-banner__close js-banner__close"></i>
<img src="/assets/images/profile.png" alt="">
</div>
<script src="/main.js"></script><script src="/assets/js/banner.js"></script>
my webpack.config.js
var path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const ASSET_PATH = process.env.ASSET_PATH || '/';
const webpack = require('webpack');
module.exports = {
entry: {
'main': './src/index.js',
'assets/js/banner': './src/assets/js/banner.js',
},
output: {
path: path.join(__dirname, "/dist"),
publicPath: ASSET_PATH ,
filename: '[name].js',
},
devServer: {
contentBase: path.join(__dirname, "/dist"),
port: 1111,
writeToDisk: true,
},
module: {
rules: [
{
test: /\.html$/,
use: [
{
loader: "html-loader",
}
]
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '/'
}
},
"css-loader",
"postcss-loader",
"sass-loader"
]
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: [
{
loader: "file-loader",
options: {
name: '[name].[ext]',
outputPath: "assets/images",
}
}
]
},
{
test: /\.(svg|eot|woff|woff2|ttf)$/,
use: [
{
loader: "file-loader",
options: {
name: '[name].[ext]',
outputPath: "assets/fonts",
}
}
]
},
]
},
plugins: [
new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/index.html",
chunks: ['main', 'assets/js/banner']
}),
new HtmlWebpackPlugin({
filename: "components/banner.html",
template: "./src/components/banner.html",
chunks: ['main', 'assets/js/banner']
}),
new HtmlWebpackPlugin({
filename: "components/button.html",
template: "./src/components/button.html",
chunks: ['main']
}),
new MiniCssExtractPlugin({filename: "assets/css/styles.css"}),
new OptimizeCSSAssetsPlugin({}),
new webpack.DefinePlugin({
'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH),
}),
],
}
project structure
the same problem in font paths, CSS, and js files
You can change publicPath in output to '' as follows:
output: {
path: path.join(__dirname, "/dist"),
publicPath: '' ,
filename: '[name].js',
},
and change the publicPath of MiniCssExtractPlugin configuration to '../../':
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../../'
}
},
You can change publicPath to the correct one on your server, by using the environment variable for example:
//...
const publicPath = process.env.BASE_URL || '/';
output: {
path: path.join(__dirname, "/dist"),
publicPath:,
filename: '[name].js',
},
//...
Related
I want to add both sass and tailwind to my project but for some reason I don't know, there is no CSS file been generated when I run webpack or maybe it does but I can't find it...
here is my webpack.config.js:
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
index: './src/index.js',
page2: './src/page2.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } },
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader',
options: {
plugins: () => [autoprefixer()]
}
}
]
},
{
test: /\.(png|jpg|gif|svg|eot|ttf|woff)$/,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.js$/i,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
},
},
},
{
// Extract any CSS content and minimize
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } },
{ loader: 'postcss-loader' }
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './dist/index.html',
inject: 'body',
chunks: ['index'],
filename: 'index.html'
}),
new HtmlWebpackPlugin({
template: './dist/page2.html',
inject: 'body',
chunks: ['page2'],
filename: 'page2.html'
}),
new MiniCssExtractPlugin({
filename: "styles.css",
chunkFilename: "[id].[contenthash].css"
})
],
devServer: {
watchContentBase: true,
contentBase: path.resolve(__dirname, 'dist'),
open: true
}
};
My postcss.config.js:
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss'),
require('postcss-preset-env')({ stage: 1 }),
require('autoprefixer')
]
};
and my tailwind.config.js
module.exports = {
purge: [ ],
darkMode: false,
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
my index.js:
import "./styles.scss";
my styles.scss:
#import "~tailwindcss/base.css";
#import "~tailwindcss/components.css";
#import "~tailwindcss/utilities.css";
.my-class {
#apply font-bold;
}
This does not work...Can someone maybe help me out?
I was having the same issue as you and ran into this answer and initially wasn't sure why you continued to encounter this issue when you already had importLoaders: 1 added to your css-loader config.
However, according to the documentation for css-loader's importLoader option, you need to change the 1 to a 2. Right now, only the postcss-loader is being imported when you also want sass-loader to be imported as well.
Here's how I would change your webpack.config.js to resolve this issue:
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
index: './src/index.js',
page2: './src/page2.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.(png|jpg|gif|svg|eot|ttf|woff)$/,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.js$/i,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
},
},
},
{
// Extract any CSS or SCSS content and minimize
test: /\.[s]?css$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 2 } },
{ loader: 'postcss-loader' },
{ loader: 'sass-loader' },
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './dist/index.html',
inject: 'body',
chunks: ['index'],
filename: 'index.html'
}),
new HtmlWebpackPlugin({
template: './dist/page2.html',
inject: 'body',
chunks: ['page2'],
filename: 'page2.html'
}),
new MiniCssExtractPlugin({
filename: "styles.css",
chunkFilename: "[id].[contenthash].css"
})
],
devServer: {
watchContentBase: true,
contentBase: path.resolve(__dirname, 'dist'),
open: true
}
};
You'll notice I also refactored your css rule into the scss rule to eliminate a bit of redundancy. That way, you only have to declare all the styling loaders only once.
I'm trying to import static html components in my templates,
I've this structure:
/src/home.html.ejs
/src/parts/header.html
/src/parts/breadcrumbs.html
/src/home.html.ejs body
<%= require('./header.html') %>
/src/parts/header.html
<h1>Title</h1>
<%= require('./breadcrumbs.html') %>
/src/parts/breadcrumbs.html
It's a breadcrumb!
When webpack is building I'm getting this in index.html:
<h1>Title</h1>
<%= require('./breadcrumbs.html') %>
Webpack config:
const path = require('path');
const miniCss = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
publicPath: '',
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.html$/,
loader: 'html-loader',
},
{
test: /\.(s*)css$/,
use: [
miniCss.loader,
'css-loader',
'sass-loader',
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
],
}
]
},
plugins: [
new miniCss({
filename: 'style.css',
}),
new HtmlWebpackPlugin({
title: 'Home',
template: path.resolve(__dirname, './src/home.html.ejs'),
filename: 'index.html',
})
],
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
}
};
Also I found a couple of solutions when devs can use option interpolate in html-loader, but I'm using html-loader higher then v0.5.5 and this option was removed
What I'm doing incorrectly?
I figured it out by using ejs-webpack-loader:
npm i ejs-webpack-loader
webpack.config.js
const path = require('path');
const miniCss = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
publicPath: '',
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.ejs$/,
use: [
{
loader: "ejs-webpack-loader",
}
]
},
{
test: /\.(s*)css$/,
use: [
miniCss.loader,
'css-loader',
'sass-loader',
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
],
}
]
},
plugins: [
new miniCss({
filename: 'style.css',
}),
new HtmlWebpackPlugin({
title: 'Home',
template: path.resolve(__dirname, './src/home.html'),
filename: 'index.html',
})
],
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
}
};
Structure
/src/home.html
/src/parts/header.ejs
/src/parts/breadcrumbs.ejs
in home.html
<%= require('./parts/header.ejs')() %>
in header.ejs
<%- require('./breadcrumbs.ejs')() %>
import child components with <%- not <%= and use brackets () in the end of import. You can pass some variables inside this brackets
in breadcrumbs.ejs
It's a breadcrumb!
I am using react and Webpack 5. After running a lighthouse report, I found a few css files that need to be preloaded. How do I do this in Webpack?
webpack config:
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require( 'path' );
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
context: __dirname,
entry: './src/index.js',
output: {
path: path.resolve( __dirname, 'build' ),
filename: '[name].js',
publicPath: '/',
chunkFilename: '[id].[chunkhash].js'
},
optimization: {
chunkIds: "named",
splitChunks: {
chunks: 'all',
},
},
devServer: {
historyApiFallback: true
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
},
{
test: /\.(png|svg|jpg|jpeg|gif|ico)$/,
exclude: /node_modules/,
use: ['file-loader?name=[name].[ext]']
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve( __dirname, 'public/index.html' ),
filename: 'index.html',
favicon: 'public/favicon.ico',
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name]-[id].css',
}),
new CopyPlugin({
patterns: [
{ from: './src/serviceWorker.js', to: './serviceWorker.js' },
{ from: './public/offline.html', to: './offline.html' },
{ from: './public/manifest.json', to: './manifest.json' },
],
}),
]
};
I tried Magic Comments (as follows) but it did not preload the css.
import (
/* webpackPrefetch: true */
/* webpackPreload: true */
'./Article.css'
);
And I tried PreloadWebpackPlugin, but I could only get it to preload all of the css files in the react project, or none at all.
Ideally, the solution would only include what is needed for the given page...
Any ideas moving forward would be appreciated. Thanks!
Well, as the title says, webpack is not producing what I expect.
Here's my config:
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const extractPlugin = new ExtractTextPlugin({
filename: 'main.css',
});
process.env.NODE_ENV = 'production';
module.exports = {
entry: {
main: './src/main.js',
algo: './src/algo.js',
},
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['es2015'],
}
}
],
},
{
test: /\.scss$/,
use: extractPlugin.extract({
use: [
'css-loader',
'sass-loader',
]
})
},
{
test: /\.html$/,
use: ['html-loader']
},
{
test: /\.php$/,
use: [
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
outputPath: '/'
}
}
]
},
{
test: /\.(jpg|png|gif|jpeg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
outputPath: 'images/',
}
}
]
}
],
},
resolve: {
alias: {
vue: 'vue/dist/vue.min'
}
},
plugins: [
extractPlugin,
new HtmlWebpackPlugin({
template: 'src/index.html',
filename: 'index.html',
chunks: ['main'],
}),
new HtmlWebpackPlugin({
template: 'src/algo.html',
filename: 'algo.html',
chunks: ['algo']
}),
new CleanWebpackPlugin([
'dist',
]),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Vue: 'vue',
}),
new CopyWebpackPlugin([
{
from: 'src/*.php',
to: '[name].[ext]',
test: /\.php$/
}
]),
],
mode: 'production',
};
Both main.js and algo.js are simply a set of #import 'something's (Please let me know if this a good practice in the comment).
I want to insert the resulting bundles, main.js and algo.js to go into
index.html and algo.html, respectively.
However, so far it's been only producing main.js for index.html so far.
Previously, the output was as follows:
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
However, that didn't work either.
Can someone help me achieve the desired outcome?
You've specified entry twice in your configuration:
entry: {
main: './src/main.js',
algo: './src/algo.js',
},
entry: './src/main.js',
The second entry here is overwriting the first, which means you've only configured ./src/main.js.
I want to exclude this from my webpack file, by using this line of code given to me below.
noParse: /node_modules\/localforage\/dist\/localforage.js/,
But no matter what I try I it keeps on saying errors like
ReferenceError: Unknown plugin "add-module-exports" specified in C:/..../node_modules\localforage\.babelrc
Here is my webpack config file:
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js',
publicPath: '/'
},
devServer: {
historyApiFallback: true,
},
module: {
rules: [
{ test: /\.(js)$/, use: 'babel-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ]}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'app/index.html'
})
]
};
You can use localForage 1.3+ version with webpack. You should add noParse in your config.
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './app/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js',
publicPath: '/'
},
devServer: {
historyApiFallback: true,
},
module: {
noParse: /node_modules\/localforage\/dist\/localforage.js/,
rules: [{
test: /\.(js)$/,
exclude: /localforage/,
use: 'babel-loader'
}, {
test: /\.css$ / ,
use: ['style-loader', 'css-loader']
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'app/index.html'
})
]
};