Webpack doesn't rendering html partials in another html partial - javascript

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!

Related

Webpack SASS and Tailwind not generating CSS file

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.

webpack assets paths in destripution folder are absolute so not working

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',
},
//...

Webpack: not producing expected bundles

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.

Why mini-css-extract-plugin does not creating css file for less?

I tried extract-text-webpack-plugin to extract css file, but it failed. The version of webpack is 4.16.3, so I use mini-css-extract-plugin to do that, failed too! I think it is not about the configuration of these plugins. There is my webpack config. the code repo is here. Success packaging,but no css file.
const baseConfig = require('./webpack.config.base')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const merge = require('webpack-merge')
const path = require('path')
const productionConfig = merge(baseConfig, {
mode: 'production',
entry: {
app: path.join(__dirname, '../src/index.js'),
vendor: ['vue', 'vue-router', 'vuex', 'axios', 'element-ui']
},
output: {
path: path.join(__dirname, '../build/public'),
filename: 'js/[name].bundle.js',
chunkFilename: 'js/[name].[chunkhash:8].chunk.js',
publicPath: './public'
},
module: {
rules: [
{
test: /\.css/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
],
include: [
path.resolve(__dirname, 'node_modules')
]
},
{
test: /\.less/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
],
include: [
path.resolve(__dirname, 'node_modules')
]
},
{
test: /\.(gif|jpg|jpeg|png|svg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 1024,
name: '[name].[hash:8].[ext]',
publicPath: './public/img',
outputPath: '/img'
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'file-loader',
options: {
limit: 80000,
name: '[name].[hash:8].[ext]',
publicPath: './public/fonts',
outputPath: '/fonts'
}
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all'
}
}
},
runtimeChunk: true
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[chunkhash:8].css',
chunkFilename: '[id].css'
})
]
})
module.exports = productionConfig

How to use noParse in webpack?

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'
})
]
};

Categories