I'm slowly bringing Webpack into an existing project. At this point we won't require .css files. However, I would like Webpack to still process them.
I would like Webpack to just load the file, pass it to whatever .css loader is required (Stylus in our case), and output a .css file.
None of the combinations of ExtractTextPlugin, raw and file loaders, passing loaders into other loaders work, Webpack inevitably throws
Module build failed: ParseError: ...bootstrap-theme.min.css:5:1996
1| /*!
2| * Bootstrap v3.3.5 (http://getbootstrap.com)
3| * Copyright 2011-2015 Twitter, Inc.
...
expected "indent", got ";"
Is it even possible to process external files with Webpack like this?
Various combinations tried:
{
test: /\.(styl|css)/,
loader: 'raw!stylus'
}
{
test: /\.(styl|css)/,
loader: 'file!stylus'
}
{
test: /\.(styl|css)/,
loader: ExtractTextPlugin.extract('file', 'raw!stylus')
}
{
test: /\.(styl|css)/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader!stylus-loader')
}
You don't need to pass your css files through the stylus loader, only the .styl files.
I've managed to make it work with this configuration:
module.exports = {
entry: {
name: './test.js'
},
output: {
filename: './bundle.js'
},
module: {
loaders: [
{
test: /\.css$/,
loaders: ['style', 'css']
},
{
test: /\.styl$/,
loaders: ['style', 'css', 'stylus']
},
{
test:/\.(woff2?|eot|ttf|svg)$/,
loader: 'url'
}
]
}
}
And then you can import/require your css files as such:
require('./test.css');
require('./node_modules/bootstrap/dist/css/bootstrap.min.css');
You could also add your CSS as an extra entry point of name:
module.exports = {
entry: {
name: [
'./test.js',
'./test.css',
],
},
/* … */
};
Related
We have a project with old-good-smarty-part and react-part.
We bundle react-part files with webpack.
We want to bundle non-react-part files with webpack too, but this files are a bit upper than webpack in project-tree. And here is a problem: we need to bundle them and place result to grand-grand-parent directory... So, how to split rules for this entry-point?
const ExtractJS = new ExtractTextPlugin({
filename: "../../[name].min.js"
});
module.exports = {
entry: {
reactApp: ["./src/entries/reactApp/index.tsx"],
// JS -- we need to place it "upper" than webpack directory in project
"scripts/oldStuff": ["./src/entries/oldStuff/index.js"]
},
module: {
rules: [
{
test: /\.js?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
cacheDirectory: true,
presets: [["es2015", { modules: false }], "stage-2", "react"],
plugins: ["transform-node-env-inline"],
env: {
development: {
plugins: ["react-hot-loader/babel"]
},
targets: {
browsers: ["last 2 versions", "ie >= 10"]
}
}
}
},
{
test: /\.js?$/,
include: [/(.*?)scripts(.*?)/, /(.*?)lib(.*?)/],
use: ExtractJS.extract({
use: {
loader: "raw-loader"
}
})
}
}
}
}
was tryed to solve this with include and exclude options, but this looks not good -- we got "cross-entry" files (something like /lib/foo/bar.js for react part and /lib/foo/boar.js for non-react part) and its about 15-20 files...
And here is a main question: is it possible to exclude entry-point for one rule and include it for another one (with exception of other entry-points)?
I have a react project that uses styled components, and I'm trying to include a CSS file as part of react-image-gallery
I followed the steps to include css-loader and style-loader in my project and tried importing the file like this
import 'react-image-gallery/styles/css/image-gallery.css
and included the following in Webpack config rules
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
}
When running the server I'm getting the below error message
SyntaxError: Invalid or unexpected token
(function (exports, require, module, __filename, __dirname) { #charset "UTF-8";
in the above CSS file
From some googling, I understood that this is because the CSS file is included as a JS file by Webpack. But isn't that how it is supposed to be?
Addition info: I have a server side rendered app.
What am I doing wrong?
Update:
My rules look like this
A rules.ts file
import webpack from 'webpack'
const ts: webpack.RuleSetRule = {
test: /^(?!.*\.spec\.tsx?$).*\.tsx?$/,
exclude: /node_modules/,
use: ['babel-loader'],
}
const img: webpack.RuleSetRule = {
test: /\.(png|jpe?g|gif|svg)$/,
use: 'file-loader',
}
const css: webpack.RuleSetRule = {
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
}
export default {
client: {
ts,
img,
css,
},
server: {
ts,
css,
img: { ...img, use: [{ loader: 'file-loader', options: { emitFile: false } }] },
},
}
A config file that has the following
const config: webpack.Configuration = {
context: path.join(__dirname, '../../src/client'),
resolve: {
...resolve.client,
alias: { 'react-dom': '#hot-loader/react-dom' },
},
devtool: false,
entry: {
main: ['./index.tsx'],
},
mode: 'development',
module: {
rules: [rules.client.ts, rules.client.img, rules.client.css],
},
output: output.client,
plugins: [
...plugins,
...developmentPlugins,
new ForkTsCheckerWebpackPlugin({
tsconfig: path.join(__dirname, '../../tsconfig.fork-ts-checker-webpack.plugin.json'),
}),
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ['!webpack.partial.html', '!favicon.ico'],
}),
],
}
We had 4 co-workers stuck on an issue like that.
Actually, we had a plugin "nodemon-webpack-plugin", which we configured for webpack.
This plugin tried to execute files like .css as java-script files.
We finally removed this plugin, because we had an up and running mon already.
I am going through webpack tutorials and it teaches how it is possible to minify and output images that have been imported in main index.js file.
However I would like to minify all image assets, regardless whether they were imported in the index.js or not. Something that was easily done in gulp by having a watch set up on the folder. Does webpack follow same format?
This is my webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules : [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
},
{
loader: 'image-webpack-loader',
}
]
}
]
}
};
No, webpack does not follow the same "logic" as gulp. Webpack """""watches""""" for changes in files that are linked throughout the entire dependency tree. This means that the file you wan't to touch HAS TO BE imported somewhere.
I'm trying to understand how to load fonts via fontawsome when loading them through a scss file:
this is my webpack config:
const path = require('path');
const webpack = require('webpack');
const UrlLoader = require('url-loader');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
publicFolder = path.resolve(__dirname, 'public');
// appFolder = path.resolve(__dirname, 'app');
module.exports = {
entry: {
// Selects main js file
main: './public/es6/index.js'
},
output: {
// Main path for the js folder
path: path.resolve(__dirname, 'public/js/'),
// Select teh name the main js file (after compression)
filename: 'bundle.js',
// Public path
// publicPath: 'http://localhost:8080',
publicPath: '/public/js/',
// Name the chunkFile (in case of external scripts)
chunkFilename: '[name].[contenthash].js'
},
module: {
rules: [ // Vue Files
{
test: /\.vue$/,
exclude: /node_modules/,
loader: 'vue-loader',
options: {
loader: {
scss: 'vue-style-loader!css-loader!sass-loader',
css: 'vue-style-loader!css-loader'
}
}
},
// JS files
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
// CSS / SASS files
{
test: /\.(sa|sc|c)ss$/,
// test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
url: false,
minimize: true,
sourceMap: true
}
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: true
}
}
]
},
// Forgot why I need this...
{
test: /\.(png|gif|jpe|jpg|woff|woff2|eot|ttf|svg)(\?.*$|$)/,
use: [{
loader: 'url-loader',
options: {
limit: 100000
}
}]
}
]
},
plugins: [
// Load jQuery globally
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
// Hot module
// new webpack.HotModuleReplacementPlugin(),
// BrowserSync: Load page automatically on change
new BrowserSyncPlugin({
proxy: 'https://potato.mywebsite.com/',
port: 3000,
files: [
'**/*.php'
],
ghostMode: {
clicks: false,
location: false,
forms: false,
scroll: false
},
minify: false,
injectChanges: true,
logFileChanges: true,
logLevel: 'debug',
logPrefix: 'webpack',
notify: true,
reloadDelay: 0
}),
// Provides a way to customize how progress is reported during a compilation
new webpack.ProgressPlugin(),
// Loads Vue
new VueLoaderPlugin(),
// For webpack-dev-server (currently not in use)
// new webpack.HotModuleReplacementPlugin(),
// Handle css in different files (scss file in login.js for example to a hashed login.css file)
new MiniCssExtractPlugin({ filename: '../css/[name].css' }),
// CSS assets during the Webpack build and will optimize \ minimize the CSS
new OptimizeCSSAssetsPlugin({}),
// Not sure if needed yet
new webpack.NamedModulesPlugin()
],
devServer: {
// https: true,
headers: { 'Access-Controll-Allow-Origin': '*' },
compress: true,
quiet: true,
hot: true,
inline: true
}
};
And this is my SCSS file where I load FontAwesome (and others)..
#import 'variable';
// Colors
#import 'colors/default';
#import 'colors/green';
#import 'colors/megna';
#import 'colors/purple';
#import 'colors/red';
#import 'colors/blue';
#import 'colors/blue-dark';
#import 'colors/default-dark';
#import 'colors/green-dark';
#import 'colors/red-dark';
#import 'colors/megna-dark';
#import 'colors/purple-dark';
// Import Bootstrap source files
#import "../../node_modules/bootstrap/scss/bootstrap";
// This is for the icons
#import '../assets/icons/font-awesome/css/fontawesome-all.css';
#import '../assets/icons/simple-line-icons/css/simple-line-icons.css';
#import '../assets/icons/weather-icons/css/weather-icons.min.css';
#import '../assets/icons/themify-icons/themify-icons.css';
#import '../assets/icons/flag-icon-css/flag-icon.min.css';
#import "../assets/icons/material-design-iconic-font/css/material-design-iconic-font.min.css";
// This is the core files
#import 'core/core';
#import 'widgets/widgets';
#import 'responsive';
// In This scss you can write your scss
#import 'custom';
When running npm run dev (or others) i don't get any error mentioning fonts.
When loading my website I get these URLS refrences in the "network" pannel:
https://mywebsite.potato.com/public/webfonts/fa-regular-400.woff
https://mywebsite.potato.com/public/fonts/Simple-Line-Icons.ttf?-i3a2kk
pointing on font files that don't even exist in my directory (or at least do't get created..)
How do I load fonts properly?
EDIT:
Adding this for #FabioCosta
{
test: /\.(png|gif|jpe|jpg|woff|woff2|eot|ttf|svg)(\?.*$|$)/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
// name: '[path][name].[ext]',
outputPath: '/public/fonts/',
publicPath: '/public/fonts/'
}
}
]
}
Adding the full module part:
module: {
rules: [ // Vue Files
{
test: /\.vue$/,
exclude: /node_modules/,
loader: 'vue-loader',
options: {
loader: {
scss: 'vue-style-loader!css-loader!sass-loader',
css: 'vue-style-loader!css-loader'
}
}
},
// JS files
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
// CSS / SASS files
{
test: /\.(sa|sc|c)ss$/,
// test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
url: false,
minimize: true,
sourceMap: true
}
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: true
}
}
]
},
{
test: /\.(png|gif|jpe|jpg|woff|woff2|eot|ttf|svg)(\?.*$|$)/,
use: [
{
loader: 'file-loader',
options: {
// name: '[path][name].[ext]',
name: '[name].[ext]',
outputPath: '/public/fonts/',
publicPath: '/public/fonts/'
}
}
]
}
Tried following: https://chriscourses.com/blog/loading-fonts-webpack
and doesn't seem to work.
Adding CSS screentshot
UPDATE
With base on the github files, you are targeting the unchanged css on the php file. That will not be parsed by webpack, remove it.
<link rel="stylesheet" type="text/css" href="css/main.css">
If you run npm run build your entry point is the JS file, this will be the parsed JS file though webpack that will generate all your files and will need to be included.
Then you are using mini css extract plugin to copy your css to somewhere, you need to load that file.
By your current configuration it is saving one level up on a css folder:
new MiniCssExtractPlugin({ filename: '../css/[name].css' }),
Whatever this file outputs is what you should be loading not the original main.css, so by your current folder structure this file would be on one level UP path. Not in the public/css that you are probably expecting, if I am not mistaken if you use ./css/[name].css it should output to where you are expecting.
As a side note here, it seems you are using the same folder for the source and output. Try to move to separated folders just so you don't overwrite anything unwillingly.
Finally the fonts:
The test of the loader needs to match your font
src: url("../webfonts/fa-brands-400.eot");
does not match the test:
test: /\.(png|gif|jpe|jpg|woff|woff2|eot|ttf|svg)(\?.*$|$)/,
You probably want to make that last part optional
test: /\.(png|gif|jpe|jpg|woff|woff2|eot|ttf|svg)(\?.*$|$)?/,
also your css-loader has url=false so the font resolver would never be invoked. Remove the url: false from your loader. Then is just a case of playing with the options of the file-loader, you can change the public-path to go to whatever you store your files and they would be replaced on the generated css and output path to copy them to the desired location.
So to summarise:
Check if you are importing the right css file, rename the file and see where it lands if you need assurance
If you want the url and the loader to be replaced , remove the url:false from css-loader and ensure the fonts files regex is matching them.
To avoid confusion store all the output on separated folder and check what lays where.
First answer:
If you are already using font-awesome and webpack I would suggest you use the font-awesome-loader.
That would be the easiest way to load them but a deeper explanation is that basically for every file extension webpack requires a loader to handle it. It will handle the file appropriately and put its contents somewhere.
So the steps to make webpack load the fontawesome fonts are:
Install the font awesome package in your project (or have the assets on some fixed place).
Load the font files using some loader like below
module.exports = {
module: {
loaders: [
// the file-loader will copy the file and fix the appropriate url
{
test: /\.(ttf|eot|svg|woff(2)?)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "fonts/",
publicPath: "../fonts/"
}
}
]
}
};
Load the appropriate CSS/SCSS/LESS from font-awesome on your css.
So analysing your code on this part:
// Forgot why I need this...
{
test: /\.(png|gif|jpe|jpg|woff|woff2|eot|ttf|svg)(\?.*$|$)/,
use: [{
loader: 'url-loader',
options: {
limit: 100000
}
}]
}
You decided to load all these extensions through url-loader so they would become base64 URIs.
You loaded all font awesome css here
#import '../assets/icons/font-awesome/css/fontawesome-all.css';
If you check the CSS it is referencing the files by a given path and you choose the url-loader so the path will not match. If you change to the file-loader and make the options match the appropriate path it will copy the files there and you should be all set to go.
I've just posted a detailed answer on another similar question like this. That could help you and also includes another possible solution with the new way of using FontAwesome5 with SVG+JS. With that there's no need for font files, Webpack loaders, etc... Just a few extra lines in your JavaScript code.
(I hope posting an answer like this is not against the rules. That another is a long writing, I don't want to copy-paste it. Should I? I don't think the duplicate flag could be used here...)
I'm trying to configure webpack of my nextJS application to handle some SASS files, which looks like this:
#font-face
font-family: 'Marcellus'
font-style: normal
font-weight: 400
src: local('Marcellus-Regular'), url('/fonts/marcellus/Marcellus-Regular.ttf') format('truetype')
The # gives me an unexpected token error. So I tried to add some custom webpack configuration:
module.exports = {
webpack: function (config) {
config.module = {
rules: [
{ test: /(\.sass$)/, loaders: ['sass-loader'] },
{ test: /(\.css$)/, loaders: ['style-loader', 'css-loader', 'postcss-loader'] },
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' }
]
}
return config
}
}
With this the *.js files aren't recognized anymore and I'm not quite sure if the SASS files are loaded correctly. I'm very unexperienced with webpack.
You need to add multiple loaders for the SASS file:
test: /\.sass$/,
use: [{
loader: 'style-loader', // creates style nodes from JS strings
}, {
loader: 'css-loader', // translates CSS into CommonJS
}, {
loader: 'sass-loader', // compiles Sass to CSS
}],
Source: Sass-loader