Webpack Image Path - wordpress

I coded my site using Webpack. Everything works except the image's path. I'm used to write ../img/test.png for it work. I've researched other questions but none work.
My files are organized inside the dist folder of the wordpress theme.
Here's my webpack.config.js :
module.exports = {
mode: 'development',
entry: [
'./src/index.js'
],
devtool: "source-map", // any "source-map"-like devtool is possible
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
},
module:{
rules:[
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
},
{
test:/\.(s*)css$/,
use: [{
loader: "style-loader", options: {
sourceMap: true
}
}, {
loader: "css-loader", options: {
sourceMap: true
}
}, {
loader: "resolve-url-loader", //resolve-url-loader needs to come *BEFORE* sass-loader
options: {
sourceMap: true
}
},{
loader: "sass-loader", options: {
sourceMap: true
}
}]
}
]
},
plugins: [
new CopyWebpackPlugin([
{from:'assets/images',to:'images'}
])
],
watch: true,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
I've tried other url-loaders but nothing seems to work. Thanks in advance.

I figured it out. The public and output path were the most important things I had to learn. Since this was with Wordpress, the other answers weren't sufficient. The new config looks like:
const webpack = require('webpack');
const path = require('path');
module.exports = {
mode: 'development',
entry: [
'./src/index.js'
],
devtool: "source-map", // any "source-map"-like devtool is possible
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
},
module:{
rules:[
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
},
{
test: /\.(png|jpe?g|gif)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'images',
publicPath: 'wp-content/themes/{{ THEME NAME }}/dist/images',
},
},
],
},
{
test:/\.(s*)css$/,
use: [{
loader: "style-loader", options: {
sourceMap: true
}
}, {
loader: "css-loader", options: {
sourceMap: true
}
}, {
loader: "sass-loader", options: {
sourceMap: true
}
}]
}
]
},
watch: true,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
Hope this helps for anyone who is working through this.

Related

Bootstrap not applying CSS using Webpack

I'm using Bootstrap with webpack, but when I run my app, no Bootstrap and no CSS is applied.
This is my webpack.config.js :
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
var OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '',
filename: 'bundle.js'
},
devServer: {
contentBase: path.join(__dirname, './build'),
compress: true,
port: 3000
},
performance: {
maxEntrypointSize: 512000,
maxAssetSize: 512000
},
module: {
rules: [
{
test: /\.s?css$/,
use: [
{
loader: "file-loader",
options: {
name: "[name].css"
}
},
{
loader: "extract-loader"
},
{
loader: "css-loader",
},
{
loader: "sass-loader"
}
]
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ["file-loader"]
},
{
test: /\.(woff(2)?|ttf|otf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
]
}
]
},
//remove comments from JS files
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
output: {
comments: false,
},
},
}),
new OptimizeCSSAssetsPlugin({
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: true } }],
}
})
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css"
}),
new ManifestPlugin(),
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve('./public/index.html'),
}),
]
};
I have this kind of error in brower console :
Uncaught Error: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/css-loader/dist/cjs.js):
CssSyntaxError
(192:1) Unknown word
I don't have an idea where this error comes from.
Below two versions of dev/prod and all the code you can see here webpack-boilerplate
Dev:
{
test: /\.(css|sass|scss)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: true
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
}
],
},
Prod:
{
test: /\.(css|sass|scss)$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: true,
importLoaders: 2
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},

MiniCssExtractPlugin + SplitChunksPlugin doesn't put scoped css into bundle

I'm using a Webpack 4 setup, where I'm trying to get all my css into a single bundle, including my scoped css from .vue files. I'm using MiniCssExtractPlugin to extract the css from the files and SplitChunksPlugin to bundle all the css into a single file. The problem is that my scoped css from .vue files is being put into separate css files.
My webpack config:
optimization: {
splitChunks: {
cacheGroups: {
common: {
test: /[\\/]node_modules[\\/].*\.js$/,
name: 'common',
chunks: 'all'
},
styles: {
test: /\.css$/,
filename: '[name]-[contenthash].css',
chunks: 'all',
enforce: true
}
}
}
},
module: {
rules: [
{
enforce: 'pre',
test: /\.(js|vue)$/,
exclude: /node_modules/,
use: 'eslint-loader'
},
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /\.(sa|sc|c)ss$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 3,
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
indentedSyntax: true
}
}
]
}
]
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
}),
new PurifyCSSPlugin({
paths: glob.sync([
path.join(__dirname, 'templates/**/*.html'),
path.join(__dirname, 'assets/js/**/*.js'),
path.join(__dirname, 'assets/js/**/*.vue')
]),
purifyOptions: {
info: true,
minify: true,
rejected: true
}
})
],
resolve: {
alias: {
jquery: 'jquery/src/jquery',
'vue': 'vue/dist/vue.js'
},
extensions: ['.js', '.vue', '.json', '.sass']
}
Output:
scoped-css-from-a-vue-file.03371a6565c9f56951dd.css // (172 bytes)
main-css-bundle-from-sass-files.af5152091d41a56d9bdd.css // (303 KiB)

webpack not getting seperate css file for extract text plugin

Hi everyone I am using web-pack to try to replace a gulp build that was overly complicated. but was running into some issues when it came to the Css. We are using sass. We also have a project structure that has the sass files right by each of the the angular component so that means for every class there is a separate folder. Currently our gulp magically goes into the folders and downloads the sass.
But I can't get the extract-text-webpack-plugin to output me a separate Css file the source I am using for trying to do this is.
https://itnext.io/sharing-sass-resources-with-sass-resources-loader-and-webpack-ca470cd11746
here is my code
const config = {
entry: {
'app': './app/app.js',
// 'vendor': './src/vendor.module.js'
},
devtool: 'source-map',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist/dev')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: [ 'ng-annotate-loader', 'babel-loader' ]
},
// for fixing of loading bootstrap icon files
{
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
loader: 'url-loader?limit=10000',
options: {
name: './fonts/[name].[ext]'
}
},
{
test: /\.(eot|ttf)$/,
loader: 'file-loader',
options: {
name: './fonts/[name].[ext]'
}
},
{
test: /\.html$/,
loader: 'html-loader',
options: {
attrs: [ 'attrs=false' ]
}
},
{
test: /\.scss$/,
use: ExtractTextWebpackPlugin.extract({
fallback: 'style-loader',
filename: path.resolve(__dirname, 'dist/dev') + 'app.css',
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
},
{
loader: 'sass-resources-loader',
options: {
resources: require(path.join(process.cwd(), './app/appscss.js'))
}
}
]
}),
},
/* ,
{
test: /\.(scss)$/,
use: ExtractTextWebpackPlugin.extract({
use: [
{
loader: "css-loader",
options: {
minimize: true
}
},
{
loader: "sass-loader"
}
]
})
} */
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
comments: false,
sourceMap: true,
}),
new ExtractTextWebpackPlugin('app.css', {
allChunks: true
}),
new webpack.DefinePlugin({
GULP_REPLACE_ENV_URL: JSON.stringify(environementUrl())
})
],
devServer: {
port: 5000,
contentBase: path.resolve(__dirname, 'dist/dev'),
historyApiFallback: true,
// needed since we set api to something other than host
// http://flummox-engineering.blogspot.com/2017/10/webpack-dev-server-invalid-host-header-host-0.0.0.0-not-working-npm-dev-server.html
disableHostCheck: true
}
};
module.exports = config;
Any help would be much appreciated.

sourceMap with sass-loader and postcss-loader in Webpack

I'm trying to enable sourceMaps in webpack but there seems to be a problem with sass-loader and postcss-loader combination.
With both sass-loader and postcss-loader enabled my console shows "no source":
But when I disable postcss-loader the sourceMap works fine and points to "typography" file:
webpack.config.js
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/dist',
filename: 'js/bundle.js',
},
devtool: 'inline-source-map',
module: {
rules: [{
test: /\.css$/i,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader']
})
},
{
test: /\.scss$/i,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
})
},
{
test: /\.js$/i,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
plugins: [
new ExtractTextPlugin('css/style.css')
]
};
main.scss
#import 'typography';
typography.scss
p {
font-size: responsive 12px 18px;
}
You can give the following a try. This is what I'm using and it's working.
{
test: /\.(sa|sc|c)ss$/,
exclude: ['/node_modules', './dist', '/src/js', '/docs'],
use: [
MiniCSSExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: true,
minimize: process.env.NODE_ENV === 'production',
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: true,
syntax: postCssScss,
plugins: () => [
autoprefixer,
postCssPresetEnv({
stage: 0,
features: {
'color-mod-function': true,
'alpha-hex-colors': true
}
}),
],
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
}
The extractTextPlugin has been deprecated for Webpack4 in favor of miniCssExtractPlugin

Styling differences in Webpack Dev versus Prod

Short Summary:
I've noticed that there are small styling discrepancies between my dev/prod configurations of webpack when testing locally. It seems to have to do with the sass-loader, but it might expand outside of that? I can't be sure because it's very difficult to track down the bug.
(Code at bottom, images just to highlight certain elements)
The Clue
The majority of styles that are missing on dev or overwritten come from my Sass file. Therefore I imagine the culprit is buried somewhere in how I process Sass files on prod.config.js versus dev.config.js. Specifically, I've noticed that variables in Sass like $main-font are not interpreted on dev, but do seem ok on prod config. I've also noticed some weird overrides happening where dev might have a border applied from a set of classes, but production doesn't. Perhaps Minicssextract is doing something differently for prod?
The Problem
In the image below, the left is my production configuration. As you can see it's extracting text into a CSS file which is called in index.html. It's loading my SCSS variables just fine. On the right, I don't use minicssextractloader and all my styles get put into tags and injected. It's switching the font-family over to something that I haven't defined anywhere in my code?
The Loader
On the left is dev, on the right is prod for Sass.
Here's how this font is defined in Sass:
Ideas and tests:
Style-loader: I tried removing postcss, sass-loader, and style-loader on dev form the scss test. Didn't seem to fix the problem.
Is there a chance webpack is doing something funky between dev/production modes?
Perhaps my css compression on prod is making things strange?
Dev.config
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
require('babel-polyfill').default;
const PATHS = {
app: path.join(__dirname, '../src'),
build: path.join(__dirname, '../dist'),
};
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: ['webpack-hot-middleware/client', './src/index'],
mode: 'development',
output: {
publicPath: '/dist/',
filename: 'bundle.js',
},
resolve: {
extensions: ['.jsx', '.js', '.json', '.scss', '.less'],
modules: ['node_modules', PATHS.app],
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'sass-loader',
],
},
{
test: /\.less$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'less-loader',
},
],
},
{
test: /bootstrap-sass\/assets\/javascripts\//,
use: [
{
loader: 'imports-loader',
options: {
jQuery: 'jquery',
},
},
],
},
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
options: '$',
},
{
loader: 'expose-loader',
options: 'jQuery',
},
],
},
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 50000,
mimetype: 'application/font-woff',
},
},
],
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream',
},
},
],
},
{
test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-otf',
},
},
],
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
},
},
],
},
{
test: /\.png$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.jpg$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.ico$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"development"',
},
__DEVELOPMENT__: true,
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.ProvidePlugin({
jQuery: 'jquery',
}),
],
};
Prod.config
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
require('babel-polyfill').default;
// const PurifyCSSPlugin = require('purifycss-webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const StatsPlugin = require('stats-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const cssnano = require('cssnano');
const PATHS = {
app: path.join(__dirname, '../src'),
build: path.join(__dirname, '../dist'),
};
const pathsToClean = [
'../dist/*.{js,css,eot,woff,woff2,svg,ttf,jpg,map}',
'../dist/index.html',
];
const cleanOptions = {
root: PATHS.build,
exclude: [
'sitemap.xml',
],
dry: false,
};
module.exports = {
// devtool: 'source-map',
entry: ['./src/index'],
mode: 'production',
output: {
publicPath: '/dist/',
chunkFilename: '[name].[chunkhash:4].js',
filename: '[name].[chunkhash:4].js',
},
resolve: {
extensions: ['.jsx', '.js', '.json', '.scss', '.less'],
modules: ['node_modules', PATHS.app],
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'sass-loader',
],
},
{
test: /\.less$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'less-loader',
},
],
},
{
test: /bootstrap-sass\/assets\/javascripts\//,
use: [
{
loader: 'imports-loader',
options: {
jQuery: 'jquery',
},
},
],
},
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
options: '$',
},
{
loader: 'expose-loader',
options: 'jQuery',
},
],
},
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
// test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 50000,
mimetype: 'application/font-woff',
},
},
],
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream',
},
},
],
},
{
test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-otf',
},
},
],
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
},
},
],
},
{
test: /\.png$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.jpg$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.ico$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
},
__DEVELOPMENT__: false,
}),
new CleanWebpackPlugin(pathsToClean, cleanOptions),
new MiniCssExtractPlugin({
filename: '[name].[contenthash:4].css',
}),
new OptimizeCSSAssetsPlugin({
cssProcessor: cssnano,
cssProcessorOptions: {
options: {
discardComments: {
removeAll: true,
},
// Run cssnano in safe mode to avoid
// potentially unsafe transformations.
safe: true,
},
},
canPrint: false,
}),
new StatsPlugin('stats.json', {
chunkModules: true,
exclude: [/node_modules[\\/]react/],
}),
// new PurifyCSSPlugin({
// paths: glob.sync(PATHS.app),
// }),
],
optimization: {
minimizer: [
new UglifyJsPlugin({
sourceMap: true,
}),
],
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'initial',
},
},
},
runtimeChunk: {
name: 'manifest',
},
},
};
Some of the Sass that seems to be having trouble?
/** 03. Typography **/
$font-source: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif;
body {
font-size: 1em;
line-height: 1.85em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: $font-source;
color: $color-secondary;
font-weight: 400;
}
Found this old q while looking into why I had a similar problem.
In my case, there was iffy css in a sass file (an opacity value set as a percentage instead of a decimal)
Dev coped with that but prod didn't. I'm still not sure why beyond "prod is more strict" - but correcting the css syntax made it work on prod (of course)

Resources