My Webpack config contains the following loaders.
module: {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/ },
{ test: /\.sass$/, loaders: ["style-loader", "css-loader", "sass-loader"], exclude: /node_modules/ }
]
},
Then, I wished to pull out the CSS to a separate file and I tried using the extract text webpack plugin, alternating my config like this.
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module: {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/ },
// { test: /\.sass$/, loaders: ["style-loader", "css-loader", "sass-loader"], exclude: /node_modules/ }
{
test: /\.sass$/,
loader: ExtractTextPlugin.extract(
{
loaders: ["css-loader", "sass-loader"],
fallbackLoader: "style-loader"
}
),
exclude: /node_modules/
}
]
},
plugins: [new ExtractTextPlugin("global.css")],...
However, it fails with. Probably due me not specifying the loaders correctly. How can I specify multiple loaders (one for SASS and one for CSS)?
Module not found: Error: Cannot resolve module '[object Object]' in C:\Source\Poc\TestProj
# ./index.js 7:14-38
I've checked the file index.js but I can't see anything wrong there. It's literally empty export, as shown below. And the reference to 7:14-38 says nothing to me. There aren't that many lines in the file, even...
import CssGlobal from "./global.sass";
//document.write("Banana!");
export default {}
This syntax for ExtractTextPlugin.extract() only works in webpack2 and above, apparently (an object as argument). Check this issue.
In order to make it work with webpack1, the syntax is:
ExtractTextPlugin.extract([notExtractLoader], loader, [options])`
notExtractLoader (optional) the loader(s) that should be used when the css is not extracted (i.e. in an additional chunk when allChunks:
false)
loader the loader(s) that should be used for converting the resource to a css exporting module.
Source: https://github.com/webpack/extract-text-webpack-plugin/blob/webpack-1/README.md
So, a working config file would be:
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
/* ... */
module : {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/ },
{
test: /\.sass$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader")
/* using ExtractTextPlugin.extract(["css","sass"]) works too */
}
]
},
plugins: [
new ExtractTextPlugin("styles.css")
]
}
This will genereate a styles.css file.
Loaders are transformations that are applied on a resource file of your app. They are functions (running in node.js) that take the source of a resource file as the parameter and return the new source.
For example, you can use loaders to tell webpack to load CoffeeScript or JSX.
Nicely Explained here
http://ui-codeman.blogspot.in/2017/02/webpack.html?view=sidebar
Related
My config file currently has the following possibly relevant code:
{
// do not exclude `node_modules`
test: /\.css$/,
loader: ExtractTextPlugin.extract(
'style-loader',
'css',
{ publicPath: '../' }
)
},
{
test: /\.scss$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract(
'style-loader',
['css-loader', 'postcss-loader', 'sass-loader'],
{ publicPath: '../' }
)
},
It's important that I run sass-loader first because PostCSS-loader (Autoprefixer) is unable to reach code within a #mixin that I have.
So far I've been unable to apply the relevant vendor prefix to the #mixin code being imported in. Everything works as expected if I move the #mixin code to where I #include it.
For Webpack 1 the extract function is expecting two parameters.
The first parameter will be applied when you're not extracting css to a file (fallback).
The second parameter is a list of loaders separated by an exclamation mark (!) , these loaders are applied from right to left.
ExtractTextPlugin.extract(
'style-loader',
'css-loader!postcss-loader!sass-loader'
);
For Webpack 2:
The ExtractTextPlugin is expecting a loader or an object.
ExtractTextPlugin.extract(options: loader | object)
Example:
{
test: /\.scss$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallbackLoader: "style-loader",
loader: [
"css-loader",
"postcss-loader",
"sass-loader"
]
})
}
I've discovered the issue in my code. My entry-point files, where the scss files were being imported, were importing as such:
import styles from '!style-loader!css!sass!postcss-loader!./styles/styles.scss'
This was overwriting the configurations in my webpack.config files, so I simply changed all my import lines to have the correct loader order.
I am trying to use sass-loader to convert SCSS files to css(Required to have physical file). Styles are getting applied but unable to see generated .css files .
//webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: './src/index.js',
output: {
path: __dirname + '/public',
filename: 'bundle.js'
},
devServer: {
contentBase: __dirname + '/public'
},
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{test: /\.scss$/, loader: ExtractTextPlugin.extract('css-loader!sass-loader')}
]
},
plugins: [
new ExtractTextPlugin("style.css")
]
}
Full source code is available at github repo
I've seen the source code. I'm sure it's because of you're still using webpack version 1 syntax but what you installed was webpack v2. Webpack2 has a different syntax than the previous version.
Using webpack v2 your webpack.config.js will look like this:
module: {
rules: [ // from 'loaders' to 'rules'
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.sass$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style-loader',
loader: ['style-loader','sass-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css') // what the output file (css) is going to be
]
Hope this helps.
I have following configurations in my webpack.config.js and package.json respectively:
var extractSCSS = new ExtractTextPlugin({filename: '[name].css', disable: false, allChunks: true});
module: {
loaders: [
{
test: /\.jsx?$/,
include: SRC_DIR,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ["react", "es2015", "stage-2"]
}
},
{
test: /\.scss$/i,
include: SRC_DIR,
exclude: /(node_modules)/,
loader: extractSCSS.extract(['css','sass'])
}
]
},
plugins: [
extractSCSS
]
and
"css-loader": "^0.26.1",
"extract-text-webpack-plugin": "^2.0.0-beta",
"style-loader": "^0.13.1",
"webpack": "^2.2.0",
But I am not able to generate the css files. Is there something I am missing here?
EDIT
I updated the files as below:
"css-loader": "^0.26.1",
"extract-text-webpack-plugin": "^2.0.0-beta.5",
"sass-loader": "^4.1.1",
"style-loader": "^0.13.1",
and
{
test: /\.css$/,
exclude: /(node_modules)/,
loader: ExtractTextPlugin.extract({
fallbackLoader: "style-loader",
loader: "css-loader",
publicPath: "/dist"
})
}
I have ExtractTextPlugin set up and it works, but it looks totally different from the configuration that you have. This is my configuration
module: {
rules: [
...
{
loader: ExtractTextPlugin.extract({
fallbackLoader: "style-loader",
loader: [
{
loader: "css-loader"
},
{
loader: "postcss-loader"
},
{
loader: "sass-loader"
}
]
}),
test: /\.s(a|c)ss$/
}
...
},
plugins: [
...
new ExtractTextPlugin({
allChunks: true,
filename: "style.[contenthash].css"
})
...
]
How it works is that the loaders get called from the back to the front. So first is the sass-loader, then the postcss-loader, etc. The fallbackLoader option is used when there is no CSS which can be extracted.
Last but not least, I want to add that I don't use ExtractTextPlugin in development, since it can result in longer build times.
Edit
I forgot to include the plugins part of my configuration. And just to clarify, the dots mean that there it is a piece of my configuration. All content relevant to the question is provided.
You have to install sass-loader
npm install --save-dev sass-loader
Note that with Webpack2 you should/have to update the configuration file :
It is not possible anymore to omit the -loader extension when referencing loaders (Automatic -loader)
module.loaders is now module.rules ( webpack 2 migration guide )
chaining loaders is only supported using the legacy option module.loaders
in V2 rule.use entry specifies a loader to be used. (rule.use)
Here is extracts of my working config :
const extractCss = new ExtractTextPlugin('app.bundle.css');
add this rules :
{
test: /\.scss$/,
loader: extractCss.extract([
{ loader: 'css-loader', query: { sourceMaps: true }},
{ loader: 'sass-loader', query: { sourceMaps: true }}
])
},
and the plugin :
plugins: [
extractCss,
Not sure if this will help, but for me moving over from Browserify I had some grief with this same issue.
I didn't realise in order for the ExtractTextPlugin to produce any css, I had to include the scss in the javascript somewhere (even though it's extracting to app.bundle.css or similar) otherwise it will silently produce no output.
application.js
require('../scss/container.scss')
or
import css from '../scss/container.scss'
will result in injected <style> tags in the header in development, and an extracted app.bundle.css file in production.
Using React with webpack.
Ran through some articles, but most of them suggest calling individual scss file for each component. But I would like to precompile all css into single file for entire application like we do using grunt/gulp.
You can use the webpack-text-extract-pluggin that is in charge of compiling all css files and bundling them in an index.css file.
Also note that you'll need to install sass-loader too in order to compile the scss.
In the webpack config:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
config = {
...,
plugins: [
...,
new ExtractTextPlugin('index.css')
],
module: {
loaders: [
...
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style','css')
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!sass')
}
]
}
}
In index.html:
<link rel="stylesheet" type="text/css" href="/index.css">
In any Javascript file that gets through webpack:
require("./styles/my-custom-file.scss");
You could take a look at the extract-text-webpack-plugin.
After requiring this in your webpack.config.js:
var ExtractTextPlugin = require("extract-text-webpack-plugin");
You can rewrite your sass loader to this:
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{test: /\.scss$/, loader: ExtractTextPlugin.extract('style', 'css', 'sass')}
]
},
plugins: [
new ExtractTextPlugin('bundle.css')
]
For more options and usage check the link above.
I'm trying to use FontAwesome in my app. I'm using webpack to do it's magic. My config is:
resolve: {
// you can now require('myfile') instead of require('myfile.cjsx')
extensions: ['', '.js', '.jsx', '.cjsx', '.coffee']
},
module: {
loaders: commonLoaders.concat([
{ test: /\.css$/, loader : 'style-loader!css-loader' },
{ test: /\.(ttf|eot|svg|woff(2))(\?[a-z0-9]+)?$/, loader : 'file-loader' },
{ test: /\.cjsx$/, loaders: ['react-hot', 'coffee', 'cjsx']},
{ test: /\.coffee$/, loader: 'coffee' },
{ test: /\.jsx$|\.js$/, loader: 'jsx-loader?harmony' },
])
}
I'm requesting FontAwesome CSS like that:
require "../../styles/font-awesome.min.css";
font-awesome.min.css contains this:
#font-face {
font-family: 'FontAwesome';
src: url('../fonts/fontawesome-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}
And for some reason, WebPack tries to parse .woff file with style-loader and gives me error:
ERROR in ./src/fonts/fontawesome-webfont.woff
Module parse failed: /var/www/app/src/fonts/fontawesome-webfont.woff Line 1: Unexpected token ILLEGAL
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
# ./~/css-loader!./src/styles/font-awesome.min.css 2:73-117
I'm really lost right now. Any ideas?
Update:
I'm completely lost right now. I've decided to fool around with my config and put this line in loaders:
{ test: /\.eot$/, loader : 'file' },
And required this file:
require "../../fonts/fontawesome-webfont.eot";
Got error:
ERROR in ./src/fonts/fontawesome-webfont.eot
Module parse failed: /var/www/app/src/fonts/fontawesome-webfont.eot Line 2: Unexpected token ILLEGAL
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
However, when I tried to require my file like this:
require "file!../../fonts/fontawesome-webfont.eot";
Everything went smooth. Looks like webpack ignores my loaders?
it depends on the url used in css.
this error is releated to regex, try to change (\?[a-z0-9]+) to (\?v=[0-9]\.[0-9]\.[0-9]) or (\?[\s\S]+).
Example:
https://github.com/gowravshekar/font-awesome-webpack
module.exports = {
module: {
loaders: [
// the url-loader uses DataUrls.
// the file-loader emits files.
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" }
]
}
};
https://github.com/shakacode/font-awesome-loader
module.exports = {
module: {
loaders: [
// the url-loader uses DataUrls.
// the file-loader emits files.
{
test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
// Limiting the size of the woff fonts breaks font-awesome ONLY for the extract text plugin
// loader: "url?limit=10000"
loader: "url"
},
{
test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
loader: 'file'
},
]
}
};
The other day I add the font-awesome through the LESS source so basically
npm install --save less-loader
bower install --save components-font-awesome
Then I require font awesome like this
require('bower_components/components-font-awesome/less/font-awesome.less')
And finally in the webpack.config.js I add the loader modules
var path = require('path')
module.exports = {
...
, module: {
loaders: [
{test: /\.less$/, loader: "style!css!less"},
{test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff'},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'}
]
}
};
I know that it not the same with .css but I believe that its easy this way. Hope it helps.