Closed Mandersen21 closed 7 years ago
You can try this below:
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract("style", "css!sass")
}
transform sass
to css
firstly
Still gives me the error: Expected 'styles' to be an array of strings.
I think this is not a webpack configuration problem, you should consider the framework you are using Are your using angular 2
Running into the same problem on angular 2. Seems as though the plugin actually strips the code out. Is there a way to force it to save content into file and return a relative url to the file generated based on the output.publicPath?
p.s. here is a solution that worked. @MwumLi you might use it. Unfortunately this is not enough for me since I am trying to use this plugin together with HtmlWebpackPlugin. Any help is much appreciated.
{
test: /\.scss$/,
loader: ['file?name=styles.css', 'css', 'sass']
}
This works for me (using extract-text-webpack-plugin v2.0.0-beta.4):
{
test: /\.sass$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: "style-loader",
loader: "css-loader!sass-loader",
}),
}
I'm having this error window is not defined
when using the extract loader.
Here's my config:
{
test: /\.s?css$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style',
loader: [
{
loader: 'css',
options: {
sourceMap: true,
modules: true,
localIdentName: NODE_ENV === 'development'
? '[name]__[local]___[hash:base64:5]'
: '[hash:base64:5]'
}
},
{
loader: 'sass',
options: {
includePaths: customPaths
}
},
{
loader: 'postcss',
options: {
plugins: () => [
autoprefixer
]
}
}
]
})
}
Same error @tleunen.
@szimek how are you importing your SCSS entry point? Like import 'scss/xx.scss';
? With your exact config, I still get window is not defined
I was getting window is not defined
because I had style-loader
in my list of loaders. When I moved it to the fallbackLoader
I stopped having that issue.
@clayne11 Very strange. My config is:
"webpack": "^2.1.0-beta.25",
"extract-text-webpack-plugin": "^2.0.0-beta.4",
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractCSS = new ExtractTextPlugin('./dist/css/[name].css');
...
{
test: /\.scss$/,
use: extractCSS.extract({
fallbackLoader: 'style-loader',
loader: 'css-loader!sass-loader',
}),
}
plugins: [ extractCSS, ...other stuff ]
I changed my entry .scss
file to just have a body { background: red; }
to eliminate any weird issue with imports.
In my index.js
entry point, import 'scss/entry.scss';
This is my config and I have it working:
import ExtractTextPlugin from 'extract-text-webpack-plugin'
...
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style',
loader: [
{
loader: 'css',
query: {
modules: true,
sourceMap: false,
localIdentName: '[hash:base64:5]',
},
},
'postcss',
],
}),
exclude: cssModuleExcludes,
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style',
loader: [
{
loader: 'css',
query: {
modules: true,
sourceMap: false,
localIdentName: '[hash:base64:5]',
},
},
'postcss',
{
loader: 'sass',
query: {
sourceMap: false,
}
}
],
}),
exclude: cssModuleExcludes,
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style',
loader: [
'css',
'postcss',
{
loader: 'sass',
query: {
sourceMap: false,
}
}
],
}),
include: cssModuleExcludes,
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style',
loader: [
'css',
],
}),
include: cssModuleExcludes,
}
plugins: [new ExtractTextPlugin('[name]-[contenthash].css', ...]
What are you excluding in cssModuleExcludes
? Wondering if it's trying to do something crazy in the node_modules
.
// cssModuleExclues
export default [
/src\/client\/ui\/styles\/normalize\.css/,
/src\/client\/ui\/styles\/index\.scss/,
/src\/client\/ui\/styles\/stylesheets\/fontcustom\.scss/,
/src\/client\/ui\/styles\/stylesheets\/icons-material-design\.scss/,
/src\/client\/ui\/styles\/stylesheets\/scaffolding\.scss/,
/src\/client\/ui\/styles\/stylesheets\/tooltips\.scss/,
/src\/client\/ui\/styles\/stylesheets\/typography\.scss/,
/node_modules/,
]
It's just a few files I have that I don't want being process with CSS modules as well as node_modules
.
So it turns out, I had a rule that was using the imports
loader, but it was looking in lib
, which what should have been a more specific rule. Gah!!!!
this issue needs to be explained better and documentation is at fault.
this explains that because style-loader is outputting js the plugin will never work. It shouldn't even be a fallback. it wouldn't work -- it is literally not the purpose of what the extract plugin is used for:
Checkout extracts explanation below.
It moves every require("style.css") in entry chunks into a separate css output file. So your styles are no longer inlined into the javascript, but separate in a css bundle file (styles.css). If your total stylesheet volume is big, it will be faster because the stylesheet bundle is loaded in parallel to the javascript bundle.
I hope this helps someone after hours of confusion...
You actually typically do want style-loader
as your fallback. When you have multiple chunks, this plugin only operates on the main chunk, not the subsequent chunks. The fallback loader will be used on non-entry chunks to process the styles.
The styles from the entry chunks will be pulled into their own CSS files but the subsequent lazy-loaded chunks will use the fallback loader and will still be inlined inside your Javascript.
@clayne11 well I would say perhaps from just css but surely not from sass or less to css. Wouldn't you agree?
Furthermore, if what fails... i.e. since the syntax is "fallback" I'll wait for your replay before I update mine and others documentations. perhaps the documentation from style-loader needs to be updated as well.
I use extract-text-webpack-plugin
with SCSS. I actually don't use style-loader
as my fallback though - I use isomorphic-style-loader
.
This is necessary for server-side rendering and code-splitting. I use isomorphic-style-loader
to gather the styles present in non-entry chunks and append it to the head of my document a style
tag. If you use style-loader
you'll get an FOUC.
Thanks @clayne11 ... do you use the isomor as a fallback or directly into the loader?
I use it as a fallback. The entry chunk is processed using extract-text-webpack-plugin
, so all the SCSS / CSS from the entry chunk is pulled into a single CSS file.
For some of my routes I use code-splitting (System.import('XXX')
), and for those routes it falls back to isomorphic-style-loader
. For SSR, I collect all the inline CSS from the code-split components and load the string in a style
tag. On the client it simply appends the styles for each component to head as an independent style tag, exactly the way style-loader
does.
The biggest downside with this approach is that it requires wrapping every single component in an HOC with a hook to load the styles for that component on mount.
This is only necessary if you do SSR and code-splitting. If you don't do both of these then you won't need to follow my approach.
Let me know if you need more info, I can share some of my SSR code and an example of how I wrap my components.
@clayne11 this is super helpful and yes it would definitely help people. I created an issue on stack and someone had a similar issue and this basically answers everything very accurately which is appreciated...
Hi, I am using webpack 2 with Angular 2 with the following loader for sass, same should also work for less.
{
test: /\.scss$/,
loader: [ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: ['css-loader'] }),
'to-string-loader',
'css-loader',
'sass-loader'
],
exclude: [helpers.root('Content')]
},
and in my component I am using
styleUrls: [ './logmonitor.component.scss' ],
my current devdependencies are:
"devDependencies": {
"@types/node": "6.0.51",
"angular2-template-loader": "0.6.0",
"awesome-typescript-loader": "2.2.4",
"css-loader": "0.26.1",
"css-to-string-loader": "0.1.2",
"file-loader": "0.9.0",
"url-loader": "0.5.7",
"html-loader": "0.4.4",
"svg-url-loader": "1.1.0",
"less": "2.7.1",
"less-loader": "2.2.3",
"node-sass": "3.13.0",
"sass-loader": "4.0.2",
"style-loader": "0.13.1",
"raw-loader": "0.5.1",
"to-string-loader": "1.1.5",
"clean-webpack-plugin": "0.1.4",
"extract-text-webpack-plugin": "2.0.0-beta.4",
"html-webpack-plugin": "2.21.0",
"webpack-notifier": "1.4.1",
"webpack": "2.1.0-beta.27",
"webpack-dev-middleware": "1.8.4",
"webpack-dev-server": "2.1.0-beta.12",
"webpack-md5-hash": "0.0.5",
"webpack-merge": "0.17.0",
"typescript": "2.0.10",
"typings": "2.0.0"
}
@sokra, any estimation on how long it will take to fully support Webpack 2 now that the first stable release (2.2.0) is out?
@cascornelissen i am using webpack 2+ and everything works the same.
@xtianus79, I'm migrating to 2.2.0 at the moment and running into the issue that the names of keys in the rules
object doesn't match the new setup.
As stated in the migration documentation, loaders.loader
should now be rules.use
but extract-text-webpack-plugin
still requires you to use the loader
key. It's not working with use
for me, at least.
Can't really remember why I added the comment to this issue though, might've been a mistake.
@cascornelissen Why have you not upgraded to 2.4.1? This is the version I am running currently
@xtianus79, 2.4.1 of what? 2.2.0 was released today.
EDIT: Ah, you were talking about Angular? I was referring the the start (and essential part) of this issue. I'm not working on anything Angular 2-specific.
I'm just interested in when the first stable 2.x release of this plugin will land as it currently doesn't support the correct syntax AFAIK.
And for anyone running into the same issues/questions, there appears to be a milestone for Wepback 2 and this is the exact problem I'm running into.
Tried all config I've found and still no one be work. This is really disturbing bugs.
I'm using "extract-text-webpack-plugin": "2.0.0-beta.5"
which seems to work with Webpack 2.
Since Google brought me here and @rohmanhm found the issue in this thread, I'll post it here in hopes of helping save someone from the hours of work of missing a single line :-p
In your app's entry JS file you must require the SASS entry point. So in my app.js I have this near the top:
require("mainCss");
then in my webpack.config I alias the path:
resolve: { alias: { 'mainCss': path.resolve( __dirname, 'sass/mainFileName.scss') } }
Still trying to work out other issues such as retaining the name of the original [filename].scss in the output file.
The loader config. {loader: ExtractTextPlugin.extract({loader: ['css-loader', 'sass-loader']}), test:/.s?css$/}
I am using Webpack 2 and extract-text-webpack-plugin@2.0.0-rc.1
My package.json:
"webpack": "2.2.1", "extract-text-webpack-plugin": "2.0.0-rc.3",
Config:
export default {
//some rules here...
modules: {
rules: [
...baseRules,
{
test: /(\.css|\.scss)$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{
loader: "css-loader",
options: {
sourceMap: true,
modules: true,
importLoaders: true,
localIdentName: "[name]__[local]___[hash:base64:5]"
}
},
{
loader: "postcss-loader",
options: {
plugins: function () {
return [
require("autoprefixer")
];
}
}
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
})
}
]
}
}
And it works finally...
Hi there, I'm using angular2 this work for me:
{
test: /\.scss$/,
exclude: [helpers.root('src', 'app')],
use: ExtractTextPlugin
.extract({
fallbackLoader: 'style-loader',
loader: [
{ loader: 'css-loader', query: { modules: true, sourceMaps: true } },
{ loader: 'sass-loader'},
{ loader: 'postcss-loader'},
]
})
},
{
test: /\.scss$/,
include: [helpers.root('src', 'app')],
use: [
{ loader: 'raw-loader'},
{ loader: 'sass-loader'},
{ loader: 'postcss-loader'}
]
}
update extract-text-webpack-plugin to v2.0.0-beta.4, it's work.
@DaWiii the new version is v2.0.0-rc.3 dude, https://github.com/webpack-contrib/extract-text-webpack-plugin/commit/e831507573feff824ef2c3c3c4a8fc971f278bc7
@whisher Hi! Curious how you got sass-loader working with webpack2/angular 2. I've been trying for a couple days now :(
Seems like it shouldn't be this hard? Just attached sass-loader and point to a directory...
@Leon Hi, you've got just the accepted answer :)
On 7 February 2017 at 22:19, Leon Gaban notifications@github.com wrote:
@whisher https://github.com/whisher Hi! Curious how you got sass-loader working with webpack2/angular 2. I've been trying for a couple days now :(
http://stackoverflow.com/questions/42058357/webpack- not-understanding-import-statement-in-my-sass-files
Seems like it shouldn't be this hard? Just attached sass-loader and point to a directory...
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/263#issuecomment-278143517, or mute the thread https://github.com/notifications/unsubscribe-auth/AAn0015GvIya2NLO2N6lfZ1mS7hPlNsNks5raN_-gaJpZM4KOx23 .
Note this variation also works (if you needed to include any options to style-loader), it's following the newer pattern:
rules: [{
test: /\.css$/,
exclude: '/node_modules/',
use: ExtractTextPlugin.extract({
fallbackLoader: [{
loader: 'style-loader',
}],
use: [{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[name]__[local]--[hash:base64:5]',
},
}, {
loader: 'postcss-loader',
}],
}),
}]
Be nice if this was documented though..
Here's my way which works with 2.0.0-rc.3
:
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
loader: [
{
loader: 'css-loader',
options: {
sourceMap: true,
minimize: true,
discardComments: {
removeAll: true
}
}
},
{
loader: 'postcss-loader',
options: {
plugins: () => [autoprefixer]
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
})
}
@webjay where do you have the autoprefixer defined
@webjay good point to have sass-loader before postcss-loader. I found clearer to use a postcss.config.js like
module.exports = {
plugins: [
require('postcss-import')(),
require('autoprefixer')()
]
}
This works for me (Angular2)
{
test: /\.css$/,
exclude: [helpers.root('src', 'app')],
use: ExtractTextPlugin
.extract({
fallback: 'style-loader',
use: [
{ loader: 'css-loader', query: { modules: false, sourceMaps: true } },
{ loader: 'postcss-loader' }
]
})
},
{
test: /\.css$/,
include: [helpers.root('src', 'app')],
use: [
{ loader: 'raw-loader' },
{ loader: 'postcss-loader' }
]
},
{
test: /\.scss$/,
exclude: [helpers.root('src', 'app')],
use: ExtractTextPlugin
.extract({
fallback: 'style-loader',
use: [
{ loader: 'css-loader', query: { modules: false, sourceMaps: true } },
{ loader: 'postcss-loader' },
{ loader: 'sass-loader', query: { sourceMaps: true } }
]
})
},
{
test: /\.scss$/,
include: [helpers.root('src', 'app')],
use: [
{ loader: 'raw-loader' },
{ loader: 'sass-loader', query: { sourceMaps: true } },
{ loader: 'postcss-loader' }
]
}
@squadwuschel Like this: import autoprefixer from 'autoprefixer';
@whisher you are not using extractText plugin in your component styles only for custom styles outside your app and could you post your package.json for devdependencies?
your solution is working for me thanks.
@squadwuschel
I use extractText plugin in my component
styles only for custom styles because I'm using
Angular2 fw
Here it is
"devDependencies": {
"@angular/compiler-cli": "2.4.3",
"@types/jasmine": "^2.5.42",
"@types/node": "^7.0.0",
"@types/webpack": "^2.0.0",
"angular2-template-loader": "0.6.0",
"assets-webpack-plugin": "^3.5.1",
"autoprefixer": "^6.7.2",
"awesome-typescript-loader": "3.0.0-beta.18",
"codelyzer": "~2.0.0-beta.4",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "0.26.1",
"extract-loader": "^0.1.0",
"extract-text-webpack-plugin": "2.0.0-rc.3",
"favicons-webpack-plugin": "^0.0.7",
"file-loader": "0.9.0",
"html-webpack-plugin": "2.26.0",
"jasmine-core": "^2.5.2",
"json-loader": "^0.5.4",
"karma": "^1.4.1",
"karma-jasmine": "^1.1.0",
"karma-phantomjs-launcher": "^1.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.2",
"loader-utils": "^0.2.16",
"ng-router-loader": "^1.0.2",
"node-sass": "^4.5.0",
"null-loader": "^0.1.1",
"phantomjs-prebuilt": "^2.1.14",
"postcss-import": "^9.1.0",
"postcss-loader": "^1.2.2",
"raw-loader": "^0.5.1",
"rimraf": "2.5.4",
"sass-loader": "^4.1.1",
"script-ext-html-webpack-plugin": "^1.5.0",
"style-loader": "0.13.1",
"ts-helpers": "1.1.2",
"ts-node": "^2.0.0",
"tslint": "~4.3.1",
"tslint-loader": "^3.3.0",
"typescript": "2.1.5",
"url-loader": "^0.5.7",
"webpack": "2.2.0",
"webpack-dev-middleware": "^1.9.0",
"webpack-dev-server": "2.2.0",
"webpack-dll-bundles-plugin": "^1.0.0-beta.5",
"webpack-md5-hash": "^0.0.5",
"webpack-merge": "~2.4.0",
"webpack-notifier": "^1.5.0"
}
@whisher I am also trying to get it working for my angular 2 app. And when I try to use your ExtractTextPlugin for my "App" folder where I have all my directives and compontens for my app I got the error
Expected 'styles' to be an array of strings. ....
Its only working when I use pure loaders like in your example on my "App" directory and the extractTextPlugin is working on my custom styles outside my "App" directory.
here so I try to load my styles all files are in the same directory where the "sxpNotifications.component.ts" is located.
@Component({
selector: '[sxp-notifications]',
templateUrl: './sxpNotifications.component.html',
styleUrls: ['./sxpNotifications.component.scss']
})
Is this still an issue? Please make sure that you are running the latest version of this plugin.
ETWP has some regressions when used with Angular 2 Components, during the fact that Angular 2 Components need the CSS at runtime => Uncaught Error: Expected 'styles' to be an array of strings.
(Angular Compiler Error), ETWP on the other hand removes
the CSS Chunks from the bundle and emits a separate CSS file, which is the correct behaviour. Use ETWP only for CSS not required directly by Angular Components { styles: require('./index.css') }
and address this issue @angular/angular to allow an empty {String} || {Array}
in styles
This worked for me with: "webpack": "^2.6.1"
and "@angular/...": "^4.1.3"
:
module: {
rules: [
{
test: /\.scss$/,
loaders: ['raw-loader', 'sass-loader']
},
{
test: /\.css$/,
loader: 'raw-loader'
}
]
}
@jsdevtom could you please post your complete webpack config? i'm having having problems with this too
@denu5 Sure. The whole project can be found here
webpack.common.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { entry: './src/app/main.ts', resolve: { extensions: [ '.js', '.ts' ] }, module: { rules: [ { test: /\.html$/, loaders: ['html-loader'] }, { test: /\.scss$/, loaders: ['raw-loader', 'sass-loader'] }, { test: /\.css$/, loader: 'raw-loader' } ], exprContextCritical: false }, plugins: [ new HtmlWebpackPlugin({ template: 'src/index.html' }) ] }
Hi
Trying to use your module to extract the text from my sass files and generate a css file with the code. I'm using Webpack version "webpack": "2.1.0-beta.22",
Code
{ test: /\.scss$/, loader: ExtractTextPlugin.extract({ fallbackLoader: "style-loader", loader: "css-loader" }) },
The code I got from your guide in github. I can build and run with "npm start", but getting an Uncaught Error: Expected 'styles' to be an array of strings. error.