When I bundling CSS from packages in node_modules, I get trouble with relativity of paths.
In original stylesheets images are requested from child folder. After bundling through Webpack folder names are right, but there is no ../ before path to image.
Attaching all, what I can provide, including project folder structure and webpack's config.
vendor.scss
#import "~leaflet/dist/leaflet.css";
#import "~leaflet-draw/dist/leaflet.draw.css";
#import "~leaflet-easybutton/src/easy-button.css";
Image imports in original leaflet.draw (css and html are in one folder)
url('images/[filename].[ext]')
Image imports after bundling (css is in child folder)
url('img/[filename].[ext]')
Folders structure
node_modules/
- leaflet-draw/
- - dist/
- - - leaflet-draw.css
- - - images/
- - - - [images]
src/
- scss/
- - vendor.scss
- index.html
dist/
- css/
- - vendor.css
- img/
- - [images from imported css]
- index.html
webpack.cofing.js
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'development',
entry: {
'vendor': [
'./src/js/vendor.js',
'./src/scss/vendor.scss'
],
'fa': './src/js/fa.js',
'sanAndreas': [
'./src/js/sa.js',
'./src/scss/sa.scss'
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].js',
sourceMapFilename: '[file].map'
},
module: {
rules: [{
test: /\.js$/,
include: path.resolve(__dirname, 'src/js'),
use: {
loader: 'babel-loader',
options: {
presets: 'env'
}
}
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {name: 'img/[name].[ext]'}
},
]
},
{
test: /\.(sass|scss)$/,
include: path.resolve(__dirname, 'src/scss'),
use: ExtractTextPlugin.extract({
use: [{
loader: "css-loader",
options: {
sourceMap: true,
minimize: true
}
},
{
loader: 'resolve-url-loader'
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
},
]
})
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
]
},
devtool: "source-map",
plugins: [
new CleanWebpackPlugin(['dist']),
new ExtractTextPlugin({
filename: './css/[name].css',
allChunks: true
}),
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html",
inject: false
}),
new HtmlWebPackPlugin({
template: "./src/sa.html",
filename: "./sa.html",
chunks: ['vendor', 'sanAndreas', 'fa']
}),
new HtmlWebPackPlugin({
template: "./src/five.html",
filename: "./five.html",
chunks: []
})
]
}
Related
When I use a relative url in an SCSS file (I am trying to set the background-image property to a local file), I receive the following error:
Any idea how what is going wrong?
I have a project with the following structure:
public/
dist/
images/
wave.png
index.html
src/
components/
MyComponent.js
app.js
styles/
base/
components/
_my-component.scss
styles.scss
webpack.config.js
In MyComponent.js I render <div className="bg"></div>.
In _my-component.scss I have:
.bg {
background-image: url("/images/wave.png");
}
And in webpack.config.js I have:
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = (env) => {
const isProduction = env === "production";
return {
entry: ["./src/app.js"],
output: {
path: path.join(__dirname, "public", "dist"),
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/
},
{
test: /\.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
sourceMap: true
}
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "styles.css"
})
],
devtool: isProduction ? "source-map" : "inline-source-map",
devServer: {
contentBase: path.join(__dirname, "public"),
historyApiFallback: true,
publicPath: "/dist/"
}
};
};
In _my-component.scss, directories are only relative to this file. According to your directory tree, you would need to go up 2 directories, which is essentially back to the root/home directory, and then one directory down to the public folder.
Try this path in your script: ../../public/images/wave.png
I've got webpack.config and don't know what module I need to place in it, cause I found modules, whitch only minimises css or scss files, but not collecting them.
So I have 8-9 scss files, and need one css file, which collects all code from them
var path = require('path');
module.exports = {
entry: {
home: './src/main/js/home/home.js',
products: './src/main/js/products/products.js',
product: './src/main/js/product/product.js',
profile: './src/main/js/profile/profile.js',
topics: './src/main/js/topics/topics.js',
topic: './src/main/js/topic/topic.js',
},
cache: true,
mode: 'development',
output: {
path: __dirname,
filename: './src/main/resources/static/built/[name].bundle.js'
},
module: {
rules: [
{
test: path.join(__dirname, '.'),
exclude: /(node_modules)/,
use: [{
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}]
}
]
}
};
What module I Should install, and where I need to put code in webpack.config. Please help, I've never worked with webpack!
var path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: {
home: './src/main/js/home/home.js',
products: './src/main/js/products/products.js',
product: './src/main/js/product/product.js',
profile: './src/main/js/profile/profile.js',
topics: './src/main/js/topics/topics.js',
topic: './src/main/js/topic/topic.js',
_article: './src/main/resources/static/sass/_article.scss',
_catalog: './src/main/resources/static/sass/_catalog.scss',
_home: './src/main/resources/static/sass/_home.scss',
_header: './src/main/resources/static/sass/_header.scss',
_footer: './src/main/resources/static/sass/_footer.scss',
},
cache: true,
mode: 'development',
output: {
path: __dirname,
filename: './src/main/resources/static/built/[name].bundle.js'
},
module: {
rules: [
{
test: [ /\.scss$/, path.join(__dirname, '.')],
exclude: /(node_modules)/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
})[{
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}]
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
};
That'smy webpack.config
webpack works different than gulp. Gulp is a task runner, which can work with globs and file patterns. Webpack is a bundler, which analyses the dependency tree given your entry points to be able to create your bundles.
In order to work with webpack, and bundle all scss files, they would need to be imported somewhere from your entry point. That is the only way that webpack will know these files exist.
Edit: Correct config.
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
home: './src/main/js/home/home.js',
products: './src/main/js/products/products.js',
product: './src/main/js/product/product.js',
profile: './src/main/js/profile/profile.js',
topics: './src/main/js/topics/topics.js',
topic: './src/main/js/topic/topic.js',
_article: './src/main/resources/static/sass/_article.scss',
_catalog: './src/main/resources/static/sass/_catalog.scss',
_home: './src/main/resources/static/sass/_home.scss',
_header: './src/main/resources/static/sass/_header.scss',
_footer: './src/main/resources/static/sass/_footer.scss',
},
cache: true,
mode: 'development',
output: {
path: __dirname,
filename: './src/main/resources/static/built/[name].bundle.js'
},
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}
}
]
},
plugins: [
new MiniCssExtractPlugin()
]
};
When I run npm run build "build": "webpack" webpack produces dist folder for me with main.css, index.html and index.js but the images from CSS or from HTML don't work and they are not there.
In CSS in dist folder they are referenced like so
background-image: url("../../../assets/img/works/works-3.jpg");
And in HTML
<img src="./assets/img/logo.png">
I'm not sure what to fix so my images are working.
I have this webpack config
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const SpritesmithPlugin = require('webpack-spritesmith');
var path = require('path');
module.exports = {
mode: 'development',
entry: './src/app.js',
module: {
rules: [
{
test: /\.css$|\.sass$|\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader?url=false'
},
{ loader: 'sass-loader' }
]
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{test: /\.png$|jpg|jpeg/, use: [
'file-loader?name=i/[hash].[ext]'
]}
]
},
resolve: {
extensions: ['.js', '.es6'],
modules: ['node_modules', 'spritesmith-generated']
},
output: {
path: __dirname + '/dist',
filename: 'index.js'
},
devServer: {
port: 8080,
contentBase: './src',
watchContentBase: true
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css'
}),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, 'src/assets/img/icons'),
glob: '*.png'
},
target: {
image: path.resolve(__dirname, 'src/spritesmith-generated/sprite.png'),
css: path.resolve(__dirname, 'src/spritesmith-generated/sprite.scss')
},
apiOptions: {
cssImageRef: '../spritesmith-generated/sprite.png'
}
})
]
};
UPD installed Copy Webpack Plugin and copied assets folder to dist folder. Images in HTML are working fine, but images in CSS do not.
After using CopyWebpackPlugin you need to need to change your background-url to /dist/images/imageName . But it depends how are structuring your build folder. This plugin copy all assets to your build folder so you need to import them from your dist folder.
I am using webpack with reactJs.
I am trying, with css, to set background-image.
when I build my project I always get the same path for img url no matter what I try.
'http://localhost:8080/images/img1.png '
instead of - 'http://localhost:8080/dist/images/img1.png'
Folder structure:
src/
App/
app.jsx
app.html
app.css
public/
images/
img1.png
img2.png
index.jsx
index.html
dist/
images/
img1.png
img2.png
bundle.js
main.bundle.css
index.html
webpack.config.js
webpack.config.js
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
// HTML plugin options
let htmlOptions = {
template: './src/index.html',
filename: 'index.html',
inject: 'body',
}
module.exports = {
entry: './src/index.jsx',
output: {
path: path.resolve('dist'),
filename: 'bundle.js',
},
resolve: {
extensions: ['.js', '.jsx', '.css']
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-3']
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.jpe?g$|\.ico$|\.gif$|\.png$|\.svg$|\.wav$|\.mp3$/,
loader: 'file-loader',
options: {
outputPath: 'img/',
name: '[name].[ext]',
publicPath: '/dist'
}
},
{
test: /\.(ttf|eot|woff|woff2)$/,
use: {
loader: "file-loader",
options: {
name: "fonts/[name].[ext]",
},
},
},
]
},
devtool: 'source-map',
plugins: [
new HtmlWebpackPlugin(htmlOptions),
new CleanWebpackPlugin(['dist']),
new CopyWebpackPlugin([{ from: __dirname + '/src/public' }])
],
devServer: {
historyApiFallback: true
}
}
app.css
body{
background-image: url('/images/loginImageBg.png');
}
**I have tried **
plugins : new ExtractTextPlugin - for some resone Conflicts with cleanWebpackPlugin.
url-loader
query: {outputPath: './data/'}
publicPath , outputPath
nothing I do seems to work
Please help !
I'm trying to use things like font-awesome and foundation with React and css modules but I can't figure it out how to import them into my project properly.
Note that I'm using HotModuleReplacementPlugin and ExtractTextPlugin to get a single css file.
Somewhere in the top-level component's css file I'd like to be able to just do #import 'font-awesome'; but how can I do it so that the file will be treated as-is and the classes won't end up localised to font_awesome__fa-check and such?
This is my webpack config:
var paths = {
app: path.join(__dirname, './app/'),
dist: path.join(__dirname, './dist/'),
external: path.join(__dirname, './node_modules/'),
}
module.exports = {
entry: {
site: [
'webpack-dev-server/client?http://localhost:5000',
'webpack/hot/dev-server',
path.join(paths.app, '/index.js'),
]
},
output: {
path: paths.dist,
publicPath: '/',
filename: 'scripts/[name].[hash].js',
chunkFilename: '[name].[chunkhash].js'
},
resolve: {
extensions: ['', '.js'],
root: paths.app,
alias: {
'font-awesome.css': path.join(paths.external, '/font-awesome/css/font-awesome.min.css')
}
},
module: {
loaders: [
{
test: /\.jsx?$/,
loaders: ['babel'],
include: path.join(__dirname, 'app')
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&localIdentName=[name]__[local]&importLoaders=1', 'postcss-loader')
}
]
},
postcss: [
require('autoprefixer-core'),
],
devtool: 'inline-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new ExtractTextPlugin("styles/[name].[chunkhash].css", {allChunks: true}),
new HtmlWebpackPlugin({
template: path.join(paths.app, '/site.html'),
filename: 'index.html',
inject: 'body',
chunks: ['site']
}),
]
};
Thanks.
You could leverage include / exclude option when configuring loaders.
E.g. given that all of your custom css is somewhere in the /app/ directory, while foundation and font-awesome are not.
...
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&localIdentName=[name]__[local]&importLoaders=1', 'postcss-loader'),
include: path.join(__dirname, 'app')
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader!css-loader'),
exclude: path.join(__dirname, 'app')
}
]
},
Another option is to use different extension for the files that use css-modules syntax. You could use .mcss.
...
module: {
loaders: [
{
test: /\.mcss$/,
loader: 'css-loader?modules&localIdentName=[name]__[local]&importLoaders=1'
},
{
test: /\.css$/,
loader: 'css-loader')
}
],
postLoaders: [
{
test: /\.(css|mcss)$/,
loader: ExtractTextPlugin.extract('style-loader')
}
]
},