How to config the file path in webpack? - css

I'm new to webpack. I want to ask how can I custom a file path in webpack.
Here is the code I've tested:
(function () {
var webpack = require('webpack'),
path = require('path'),
BabiliPlugin = require('babili-webpack-plugin'),
ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: {
'site': ['./assets/js/site']
},
output: {
publicPath: '/assets/',
path: path.join(__dirname, 'wwwroot/assets/js'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.js$/i,
use: [{
loader: 'babel-loader',
query: {
presets: ['es2015', 'stage-1'],
compact: false
}
}]
},
{
test: /(\.(ttf|eot|svg)(\?[\s\S]+)?$)|(\.woff2?(\?v=\d+\.\d+\.\d+)?$)/,
use: [{
loader: 'file-loader',
options: {
name: '../fonts/[name].[ext]'
}
}]
},
{
test: /\.(png|jpe?g|bmp|gif|ico)/,
use: [{
loader: 'file-loader',
options: {
name: '../images/[name].[ext]'
}
}]
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract(['css-loader'])
}
]
},
plugins: [
new BabiliPlugin({}, { test: /\.min\.js$/ }),
new webpack.ProvidePlugin({
$: 'jquery'
}),
new ExtractTextPlugin('../css/bundle.css')
]
};
}());
I want to ask about these lines:
use: [{
loader: 'file-loader',
options: {
name: '../fonts/[name].[ext]'
}
}]
When I set the name starts with ../, it compiles exactly right except the url which is inside the file bundle.css, like this snapshot:
Then, I've tried to remove the characters ../ from the name, the fonts folder was created inside js folder (it's not my goal). But the url inside the file bundle.css folder is right (I want this path - /assets/fonts/...).
How can I edit it?
p/s: May you embed the two images to my question? it doesn't appear now. Thank you!

You may need to set a context in your loader's options. By default the current working directory is used.
I'm not sure what your src directory structure is, so I'm taking a guess.
use: [{
loader: 'file-loader',
options: {
name: 'assets/fonts/[name].[ext]',
context: './src/assets/fonts/'
}
}]

Related

Configure fonts in webpack

I have a slight problem with webpack here; I'm somewhat unable to load fonts.
This is my webpack.config.js
const nodeExternals = require('webpack-node-externals');
const path = require('path');
const devMode = true;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry:
[
'./src/main.js',
'./scss/main.scss'
],
output: {
filename: "main.min.js",
chunkFilename: '[name].bundle.min.js?bust=[chunkhash]',
path: path.resolve(__dirname, 'static_root'),
publicPath: "/assets/"
},
target: "node",
externals: [nodeExternals()],
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.scss$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].css',
outputPath: 'css/'
}
},
{
loader: 'extract-loader'
},
{
loader: 'css-loader'
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
hmr: process.env.NODE_ENV == 'development',
}
},
],
},
{
test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '[name].[ext]'
}
}
]
}
};
This builds my css although then my local fonts aren't included / aren't rendered.. This also copies my Font to /static_root (which is where the css gets built to).
so I end up with this directory structure:
public/static_root/css/main.css
public/static_root/BebasNeue-Regular.ttf
public/static_root/main.min.js
I thought about just adjusting the path to the font in my scss file unfortunately though this lets the build process fail, since my working dir and the output root aren't the same.
My scss/font-directory is structured like so:
/public/scss/fonts/_fonts.scss
/public/scss/fonts/BebasNeueRegular.ttf
/public/scss/main.scss
So how can I achieve the inclusion of the font or how is this usually done since I found lots of different approaches online, that sadly didn't work out for me.
Any help would be greatly appreciated.
Greetings,
derelektrischemoench
So I found out what was causing the problems. It had to do something with the loader for the fonts (I was using an older one). I tried the whole thing with the url-loader like so:
{
test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '[name].[ext]'
}
}
... which got it going. It was just kinda confusing, since I found a bazillion of tutorials on the web on how to achieve this, of which the most part was deprecated.
Thanks for the responses.
hey #derelektrischemoench, I think the example in Webpack official website is pretty good, you could follow the webpack config and its file structure:
https://webpack.js.org/guides/asset-management/#loading-fonts

Webpack 4: mini-css-extract-plugin + file-loader not loading assets

I'm trying to move assets (images and fonts) used in one of my .scssfiles, but it seems that they get ignored:
This is my .scss file:
#font-face {
font-family: 'myfont';
src: url('../../assets/fonts/myfont.ttf') format('truetype');
font-weight: 600;
font-style: normal;
}
body {
color: red;
font-family: 'myfont';
background: url('../../assets/images/bg.jpg');
}
And this is my webpack.config.js:
const path = require('path');
const { CheckerPlugin } = require('awesome-typescript-loader');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
target: 'node',
entry: path.resolve(__dirname, 'server.tsx'),
output: {
filename: 'server_bundle.js',
path: path.resolve(__dirname, 'build'),
publicPath: '/build'
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
module: {
rules: [{
test: /\.(tsx|ts)?$/,
loader: 'awesome-typescript-loader',
options: {
jsx: 'react'
}
},
{
test: /\.(scss|sass|css)$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { url: false, sourceMap: true } },
{ loader: 'sass-loader', options: { sourceMap: true } },
]
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/,
loader: 'file-loader',
options: { outputPath: 'public/images' }
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader',
options: { outputPath: 'public/fonts' }
}
]
},
plugins: [
new CheckerPlugin(),
new MiniCssExtractPlugin({
filename: 'public/styles_bundle.css',
chunkFilename: "public/styles/[id].css"
})
]
}
I'm getting this .css file in my browser as the output (Note the name of the image):
body {
color: red;
background: url("../../assets/images/myimage.jpg");
}
And in my public directory I get this:
public/
styles_bundle.css
There are two problems here:
Fonts are not compiled (No public/fonts/etc...)
Images are not compiled
I've been trying everything, but I don't know what may be happening here... Any Ideas?
I have just fixed a similar issue. If you change the url option to true, you might see failed image URL references.
{ loader: 'css-loader', options: { url: false, sourceMap: true } },
Or you can manual check whether the path reference is correct.
url('../../assets/images/bg.jpg')
I think the images folder doesn't get created because all the image resource links are incorrect.
For the problem I was fixing, the references were all wrong and I couldn't fix them so I just used this webpack copy plugin to copy files to the right dist folder location.
you need url-loader
{
test: /\.(jpg|png|gif|woff|eot|ttf|svg)/,
use: {
loader: 'url-loader', // this need file-loader
options: {
limit: 50000
}
}
}
try the below configuration
{
test: /\.s[ac]ss$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: ''
}
},
{
loader: "css-loader",
options: { sourceMap: true}
},{
loader: "sass-loader",
options: { sourceMap: true }
}
]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
loader: 'file-loader',
options: { outputPath: 'assets/images', publicPath: '../images', useRelativePaths: true }
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
loader: 'file-loader',
options: { outputPath: 'assets/fonts', publicPath: '../fonts', useRelativePaths: true }
}
After this my scss file started accepting the relative URL and the compiled files also mapped accordingly using relative path.
The mini-css-extract-plugin has a 'publicPath' option (see here). It basically tells the generated css where the external resources like fonts, images, etc are to be found. In my case, setting it to '../' and configuring all the file loaders to their proper directories, this worked perfectly.
Basically looks like:
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '/public/path/to/', // <-- This is what was helping.
},
},
'css-loader',
],
},
],
I had this issue too. I was using the following versions:
package.json
"mini-css-extract-plugin": "^0.10.1",
"webpack": "^5.3.1",
For me everything was compiling just fine until I added the following into a scss file:
.xmas {
background-image: url("./img/Xmas2020/SurveyBanner.png");
height: 150px;
}
The backgound-image url was the problem. When I changed it to an absolute path it worked:
.xmas {
background-image: url("/img/Xmas2020/SurveyBanner.png");
height: 150px;
}
webpack.config.js
This is just to show how I was putting images into the output directory. I guess there are different ways to do this, but I was using CopyWebpackPlugin.
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: './src/static/img', to: './img', force: true },
]
}),
]
This link helped me https://github.com/webpack-contrib/mini-css-extract-plugin/issues/286#issuecomment-455917803
Had the exact problem with webpack 5. The answer is in Asset Modules
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: 'images/[hash][ext][query]' //set the pattern for your filename here
},
module: {
rules: [
{
test: /\.png/,
type: 'asset/resource' //replaces file-loader, url-loader etc
}
]
},
};

How can I grab bunch of scss files and make one css file for all application

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

Window is not defined (Server-side rendering with Asp.Net SPA Services)

Thank you guys for reading my question. Really hoping for a solution to this, I've been trying to find a fix for days to no avail.
Here's the rundown: My goal is to render a React application on the server-side using .NET Core. I haven't even started with the react part yet, right now I'm simply trying to render an h1 tag with the ASP.NET Javascript Services Prerendering functionality.
On my first iteration, I wrote my boot-server.js file with es5 and it worked perfectly. However, I quickly realized I was going to need to compile the file through webpack in order for it to understand my React code.
As soon as I piped that file through webpack though, I got a "window is not defined" error which I haven't been able to fix. I understand that part of my application should not be aware of the window object since it lives in the server but setting the webpack config's target field to node does not seem to fix the issue. Below are all the files involved.
Here is my boot-server.js file:
import { createServerRenderer } from 'aspnet-prerendering';
module.exports = createServerRenderer((params) => {
return new Promise((resolve, reject) => {
var html = '<h1>Hello world!</h1>';
resolve({
html: html
});
});
});
Here is my cshtml view:
#addTagHelper "*, Microsoft.AspNetCore.SpaServices"
<app id="root" asp-prerender-module="wwwroot/client/boot-server.bundle">Loading...</app>
Here is my webpack.config.js file:
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const path = require("path");
const clientConfig = {
entry: './FrontEnd/index.js',
output: {
path: path.resolve(__dirname, "wwwroot/client"),
filename: "client.min.js",
publicPath: "/client/"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["es2015", "react", "stage-0"],
plugins: ["transform-class-properties", "transform-decorators-legacy", "react-html-attrs"]
}
}
},
{
test: /\.scss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "sass-loader"
}]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader?name=[name]_[hash:8].[ext]'
]
}
]
},
mode: 'development',
devServer: {
contentBase: './wwwroot/client',
hot: true
}
};
const bootServerConfig = {
stats: { modules: false },
resolve: { extensions: ['.js'] },
output: {
filename: '[name].js',
publicPath: '/wwwroot/client/', // Webpack dev middleware, if enabled, handles requests for this URL prefix
libraryTarget: 'commonjs'
},
entry: {
'main-server': './FrontEnd/boot-server.js'
},
module: {
rules: [
{
test: /\.js$/,
include: /FrontEnd/,
use: [
{
loader: "babel-loader",
options: {
presets: ["es2015", "react", "stage-0"],
plugins: ["transform-class-properties", "transform-decorators-legacy", "react-html-attrs"]
}
}
]
},
{
test: /\.svg$/,
use: {
loader: 'url-loader',
options: { limit: 25000 } //?limit=100000'
}
}
]
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './wwwroot/client')
},
target: 'node'
}
module.exports = [clientConfig, bootServerConfig];
Here is a screenshot of the error page:

Webpack: extract css to its own bundle

I'm using webpack on a project. I use style-loader so I can import "my.css".
The css gets bundled with the javascript and will be rendered in a <style> tag when component mount, ok.
However, I would like to keep that import syntax and make webpack build a css bundle for every entry point.
So webpack output should be [name].bundle.js AND [name].bundle.css.
Is this something I can achieve ?
var config = {
entry: {
'admin': APP_DIR + '/admin.entry.jsx',
'public': APP_DIR + '/public.entry.jsx'
},
output: {
path: BUILD_DIR,
filename: '[name].bundle.js'
},
resolve: {
extensions: ['.js', '.jsx', '.json']
},
plugins: [],
devtool: 'cheap-source-map',
module: {
loaders: [{
test: /(\/index)?\.jsx?/,
include: APP_DIR,
loader: 'babel-loader'
},
{
test: /\.scss$/,
loaders: [
'style-loader',
'css-loader',
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: ['./src/styles/constants.scss']
},
}
]
}
],
}
};
along with this babel.rc:
{
"presets" : ["es2015", "react"],
"plugins": ["transform-decorators-legacy", "babel-plugin-root-import"]
}
Yes, you need to use extract-text-webpack-plugin. You might want to do it only on your production config. Config looks like this:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: ['css-loader', 'sass-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin('style.css')
//if you want to pass in options, you can do so:
//new ExtractTextPlugin({
// filename: 'style.css'
//})
]
}

Resources