ouput css file rather than inline - node.js

How to ouput css file as file.css rather than inline in javascript. My configuration look like below.
{
test: /\.less$/,
loader: "style-loader!css-loader!less-loader"
}
I tested with
"file-loader!css-loader!less-loader" //but the content of the file is not css

You would have to use the extract-text-plugin. You can create one css file for your entire bundle or one for each chunk. For example if you want all your CSS in your bundle moved to a separate file, you would add this to your figuration
module.exports = {
loaders: [
// Extract css files
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
// Optionally extract less files
// or any other compile-to-css language
{
test: /\.less$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
}
],
plugins: [
new ExtractTextPlugin("[name].css", {
allChunks: true
})
]
}
See stylesheets webpack configuration for more reference

Related

Module parse failed for one specific node_module, how do you solve it? (details inside)

I have a project, that when I build the UI, it keeps returning “Module parse failed”.
The problem is VERY similar to this one https://github.com/TypeStrong/ts-loader/issues/867, the only difference is that instead of a static variable, it is the initialization of a variable, like this:
export class AppWebsocket {
client; // WEBPACK SAYS THIS LINE HAS THE ERROR
defaultTimeout;
overrideInstalledAppId;
constructor(client, defaultTimeout, overrideInstalledAppId) {
// Some code
}
}
This problem appears after I am importing something new from a new dependency (the AppWebsocket). The AppWebsocket belongs to a new dependency I’ve installed. And I am importing the AppWebsocket in one of my files.
The problem to this is related to webpack and the rules for the modules according to the link.
On my webpack configuration I have this:
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-react'],
plugins: [],
},
},
},
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: 'ts-loader',
},
The problem seems to be fixed, if I turn it into this:
{
test: /\.js$/,
use: 'ts-loader',
},
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: 'ts-loader',
},
The problem is that I don’t understand what are the consequences of this. My project uses react.
I need to solve the webpack problem, but I am not sure what I am doing. Any help to understand or to fix this issue is appreciated.

Webpack file-loader with sass-loader

I am new to nodejs and get a problem when trying to use sass with it.
The following information is just fictional, but it represents the
actual condition.
THE SCENARIO:
I have the following folder structure:
frontend/
- scss/
- style.scss
- main.js
webpack.config.js
Goal:
I want to compile the style.scss to style.css using webpack and put it inside dist/frontend/css/ directory, so it should be resulting this path: dist/frontend/css/style.css and create the following folder structure:
dist/
- frontend/
- scss/
- style.scs
- main.js
frontend/
- scss/
- style.scss
- main.js
webpack.config.js
THE CODES:
main.js
import `style from "./scss/style.scss";`
webpack.config.js
module.exports = {
mode: "development",
entry: {
main: "./frontend/main.js"
},
output: {
path: path.join(__dirname, "/dist/frontend"),
publicPath: "/",
filename: "[name].js"
},
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
{
loader: "file-loader",
options: {
name: "css/[name].[ext]"
}
},
"style-loader/url",
"css-loader?-url",
"sass-loader"
]
}
]
}
THE RESULT:
I get this message:
Module not found: Error: Can't resolve './scss/style.scss' in 'E:\project_name\frontend'
THE QUESTIONS
Why is that happening?
What is the correct codes to achieve the Goal?
As the message said, this path is not valid: './scss/style.scss'. There are typo when defining the path. The folder is supposed to be sass instead of scss.
The following configuration will work to achieve the Goal mentioned in the question:
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
"style-loader/url",
{
loader: "file-loader",
options: {
name: "css/[name].css"
}
},
"sass-loader"
]
}
]
}
It works like Mini CSS Extract Plugin, but does not generating additional .js files for each .css file when used to convert multiple .scss files into different .css files.

How to use relative paths with node-loader and native addon

I have a native addon I am using that works great on my dev machine but fails on any other machine due to the webpack build using an absolute path to the native module instead of a relative one. Here is the error I get:
/main.prod.js:7543: Uncaught Error: Cannot open /Users/.../app/lib/main.node: Error: dlopen(/Users/.../app/lib/main.node, 1): image not found
In my main.dev.js I import the file like this: import main from './lib/main.node';
In webpack config I have added a module test for .node:
export default {
externals: Object.keys(externals || {}),
module: {
rules: [{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
}, {
test: /\.node$/,
use: 'node-loader'
}]
},
...
How can I make sure that my main.node file gets packaged for the build and imported via relative path?
I was able to resolve this issue by switching to a modified version of node-addon-loader. https://github.com/smt116/node-native-ext-loader

Differentiate between SVG images and fonts in webpack loader

I'm trying to create a Webpack loader, and all other file types are working; however, when it comes SVGs, the loader gets confused and empties the SVG image document via the font loader. Below is the code I am using...
/* Images still being loaded in this test for some reason */
{
test : /\.svg/,
exclude: '../src/images',
loader : 'file?prefix=font/'
},
{
test : /\.svg/,
include: '../src/images',
loader : 'file-loader'
}
As you can see, I have tried using include/exclude in the tests, however, this hasn't worked.
Any ideas?
To fix this, I just used RegEx to exclude any path containing images, like so...
// FONT LOADER
{
test : /\.svg/,
exclude: [/images/],
loader : 'file?prefix=font/'
},
// OTHER FILES LOADER
{
test: /\.(mp4|ogg|svg)$/,
loader: 'file-loader'
}

How do I load font-awesome using SCSS (SASS) in Webpack using relative paths?

I have font-awesome in my node_modules folder so I try to import it in my main .scss file like so:
#import "../../node_modules/font-awesome/scss/font-awesome.scss";
But Webpack bundling compilation fails, telling me
Error: Cannot resolve 'file' or 'directory' ../fonts/fontawesome-webfont.eot
because the font-awesome.scss file refers to a relative path, '../fonts/'.
How can I tell scss \ webpack to #import another file, and use that file's folder as the home folder so that its relative paths work as it expects?
Use
$fa-font-path: "~font-awesome/fonts";
#import "~font-awesome/scss/font-awesome";
where the $fa-font-path variable is seen in font-awesome/scss/_variables.scss
$fa-font-path: "../fonts" !default;
The tilde "~" is interpolated by sass-loader using the webpack mecanism.
There doesn't appear to be any way to #import files that have their own relative paths in SCSS \ SASS.
So instead I managed to get this to work:
Import the scss \ css font-awesome file in my .js or .jsx files, not my stylesheet files:
import 'font-awesome/scss/font-awesome.scss';
Add this to my webpack.config file:
module:
{
loaders:
[
{test: /\.js?$/, loader: 'babel-loader?cacheDirectory', exclude: /(node_modules|bower_components)/ },
{test: /\.jsx?$/, loader: 'babel-loader?cacheDirectory', exclude: /(node_modules|bower_components)/ },
{test: /\.scss?$/, loaders: ['style-loader', 'css-loader', 'sass-loader']},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml'},
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/octet-stream"},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader"},
]
}
Following worked for me:
$fa-font-path: "~font-awesome/fonts";
#import "~font-awesome/scss/font-awesome";
This is to import the font-awesome & required fonts in the project.
Other change is in webpack configurations, to load required fonts using file-loader.
{
test: /\.scss$/,
loaders: ['style', 'css?sourceMap', 'sass'
],
}, {
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)(\?.*$|$)/,
loader: 'file'
}
This is how it worked for me, the trick is to set $fa-font-path to the path of the fonts as following.
$fa-font-path: "~#fortawesome/fontawesome-free/webfonts/";
#import '~#fortawesome/fontawesome-free/scss/fontawesome.scss';
#import '~#fortawesome/fontawesome-free/scss/solid.scss';
#import '~#fortawesome/fontawesome-free/scss/brands.scss';
Note: Please check your fonts folder in node_modules in my case it is #fortawesome/fontawesome-free
Resolved by changing my app.scss:
#import '~font-awesome/scss/_variables.scss';
$fa-font-path: "~font-awesome/fonts";
#import '~font-awesome/scss/font-awesome.scss';
This way is useful to keep external dependencies unchanged and unversioned.
I just set the path in my main scss file and it works :
$fa-font-path: "../node_modules/font-awesome/fonts";
#import '~font-awesome/scss/font-awesome.scss';
What worked for me was to add resolve-url-loader and enable sourceMaps
I already imported font-awesome in my root .scss file:
#import "~font-awesome/scss/font-awesome";
...
This root file is imported in my main.js file defined as Webpack's entrypoint:
import './scss/main.scss';
...
Then my final webpack module rules look like so:
...
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{ loader: 'postcss-loader', options: { sourceMap: true }, },
'resolve-url-loader',
{ loader: 'sass-loader', options: { sourceMap: true }, },
],
}, {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: { limit: 1000, name: 'fonts/[name].[ext]', },
}
...
Note:
I used mini-css-extract-plugin, which can be registered like this:
new MiniCssExtractPlugin({
filename: 'css/main.css',
chunkFilename: '[id].[hash]',
}),
url-loader requires file-loader to be installed, so if you get an error like: cannot find module file-loader, then just install it:
npm i -D file-loader
Useful Links:
https://github.com/webpack/webpack/issues/2771#issuecomment-277514138
https://github.com/rails/webpacker/issues/384#issuecomment-301318904
For Version 5.14, the following worked for me:
$fa-font-path : '../node_modules/#fortawesome/fontawesome-free/webfonts';
#import "../node_modules/#fortawesome/fontawesome-free/scss/solid";
#import "../node_modules/#fortawesome/fontawesome-free/scss/brands";
#import "../node_modules/#fortawesome/fontawesome-free/scss/fontawesome";
v.4 (symofony 4 + webpack)
$fa-font-path: "~components-font-awesome/webfonts";
#import '~components-font-awesome/scss/fa-brands';
#import '~components-font-awesome/scss/fa-regular';
#import '~components-font-awesome/scss/fa-solid';
#import '~components-font-awesome/scss/fontawesome';

Resources