Uncaught Error: Expected 'styles' to be an array of strings - css

I have tried solutions proposed for this identical error message without success. When i run my angular project with the angular cli through ng serve, the project runs fine without errors. However, when i compile it with webpack, i get the (full) error message:
Uncaught Error: Expected 'styles' to be an array of strings.
at z (vendor.js:1)
at t.getNonNormalizedDirectiveMetadata (vendor.js:1)
at t.loadDirectiveMetadata (vendor.js:1)
at vendor.js:1
at Array.forEach (<anonymous>)
at vendor.js:1
at Array.forEach (<anonymous>)
at t._loadModules (vendor.js:1)
at t._compileModuleAndComponents (vendor.js:1)
at t.compileModuleAsync (vendor.js:1)
at e._bootstrapModuleWithZone (vendor.js:1)
at e.bootstrapModule (vendor.js:1)
at Object.<anonymous> (app.js:1)
at Object.199 (app.js:1)
at e (vendor.js:1)
at window.webpackJsonp (vendor.js:1)
at app.js:1
My webpack.config.js:
// Plugins
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// Config
module.exports = {
entry: {
app: "./src/main.ts",
vendor: ["./src/vendor.ts", "./src/polyfills.ts"]
},
output: {
publicPath: "",
path: __dirname + "/dist/",
filename: "[name].js"
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
loaders: [
{
loader: "awesome-typescript-loader",
options: { tsconfig: "tsconfig.json" }
}, "angular2-template-loader"
]
},
{
test: /\.(html)$/,
loaders: [
{
loader: "html-loader"
}
]
},
{
test: /\.(css|scss)$/,
loaders: ['to-string-loader', 'css-loader', 'sass-loader']
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
comments: false
}),
new webpack.optimize.CommonsChunkPlugin({
names: ["app", "vendor"]
}),
new HtmlWebpackPlugin({
template: "src/index.tpl.html",
inject: "body",
filename: "index.html"
})
]
}
.angular-cli.json
{
"apps": [
{
"root": "src",
"outDir": "dist",
"index": "index.tpl.html",
"main": "main.ts",
"polyfills": "polyfills.ts"
}
],
"defaults": {
"styleExt": "css"
}
}
app-root / app.component.ts
import { Component } from "#angular/core";
import { Observable } from "rxjs/Rx";
import { NgFor } from "#angular/common";
#Component ({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
}
Any suggestions as to what i am doing wrong?

This was my webpack setup that worked for scss and css files. For this setup (using Angular Storybook, so this webpack config was located in ./storybook), I had a global stylesheet in app/styles that needed some extra massaging because it imported other stylesheets in that directory that used relative paths. I also had a custom stylesheet in the same directory as this webpack (./):
webpack.config.js
const path = require('path');
const autoprefixer = require('autoprefixer');
const postCSSCustomProperties = require('postcss-custom-properties');
const postcssPlugins = () => [
require('postcss-flexbugs-fixes'),
autoprefixer({ flexbox: 'no-2009' }),
postCSSCustomProperties({ warnings: true })
];
module.exports = (baseConfig, env, config) => {
baseConfig.module.rules = [
...baseConfig.module.rules.filter(r => !r.test.toString().includes(".s(c|a)ss")), // base rules supplied by Angular Storybook
...
{
test: /\.css$/,
use: [
'raw-loader',
{
loader: 'postcss-loader',
options: {
plugins: postcssPlugins
}
}
]
},
{ // component scss loader
test: /\.scss$/,
include: [path.resolve(__dirname, '../')],
exclude: [path.resolve(__dirname, '../app/styles'), path.resolve(__dirname, './')],
use: [
'raw-loader',
{
loader: 'postcss-loader',
options: {
plugins: postcssPlugins
}
},
'sass-loader'
]
},
{ // global and storybook scss loader
test: /\.scss$/,
include: [path.resolve(__dirname, '../app/styles'), path.resolve(__dirname, './')],
loaders: [
'style-loader',
'css-loader',
'resolve-url-loader', // resolves relative imports
'sass-loader?sourceMap' // sourcemap = true to assist resolve-url-loader
]
},
...
];
baseConfig.resolve.extensions.push(".css", ".scss");
baseConfig.resolve.alias = {
...baseConfig.resolve.alias,
"assets": path.resolve(__dirname, "../app/assets") // needed to resolve relative paths in imported scss using an alias, where the imported files referred to sheets like "url(~assets/path/to/pic.jpg)"
}
return baseConfig;
};
package.json
"dependencies": {
"#angular/core": "^6.1.3",
"resolve-url-loader": "^3.0.0",
},
"devDependencies": {
"#ngtools/webpack": "6.0.8",
"#storybook/angular": "^4.1.4",
"css-loader": "^0.28.11",
"postcss-custom-properties": "^7.0.0",
"postcss-flexbugs-fixes": "^3.3.1",
"postcss-loader": "^2.1.5",
"raw-loader": "^0.5.1",
"sass-loader": "^7.0.3",
"style-loader": "^0.23.1",
"webpack": "4.15.0"
}

I solved my issue, by following Shobhit's suggestion, adding the following to webpack.config.json:
...
rules: [
{
test: /\.(scss|css)$/,
use: ["raw-loader", "sass-loader"]
},
{
test: /\.scss$/,
exclude: [/node_modules/, /src\/app/],
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "sass-loader"]
})
}
...
And
plugins: [
new ExtractTextPlugin("styles.css")
...

Related

Not able to import css files in react

In App.js I wanted to import App.css file or any css file. import './App.css' is not working here and giving error " ERROR in ./src/shared/App.css 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders "
Directory Structure -
1. public
- bundle.js
2. src
- browser (folder) > index.js
- server (folder) > index.js
- server (folder) > App.js , App.css
This is my webpack.config.js file -
var path = require('path')
var webpack = require('webpack')
var nodeExternals = require('webpack-node-externals')
var combineLoaders = require('webpack-combine-loaders');
var browserConfig = {
entry: './src/browser/index.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/'
},
module: {
rules: [
{ test: /\.(js)$/, exclude: /node_modules/, use: ['babel-loader']},
{
test: /\.css$/,
exclude: /node_modules/,
loader: combineLoaders([
{
loader: 'style-loader'
}, {
loader: 'css-loader',
query: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
])
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx', '.css']
},
mode: 'production',
plugins: [
new webpack.DefinePlugin({
__isBrowser__: "true"
})
]
}
var serverConfig = {
entry: './src/server/index.js',
target: 'node',
externals: [nodeExternals()],
output: {
path: __dirname,
filename: 'server.js',
publicPath: '/'
},
mode: 'production',
module: {
rules: [
{ test: /\.(js)$/, exclude: /node_modules/, use: ['babel-loader']},
{
test: /\.css$/,
exclude: /node_modules/,
loader: combineLoaders([
{
loader: 'style-loader'
}, {
loader: 'css-loader',
query: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}
])
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx', '.css']
},
plugins: [
new webpack.DefinePlugin({
__isBrowser__: "false"
})
]
}
module.exports = [browserConfig, serverConfig]
To load CSS files in your ReactJS project, install the css-loader for ReactJS...
npm install --save-dev style-loader css-loader
Also, make sure to modify your webpack.config.js file, located in my project at: ./node_modules/webpack-dev-server/client/webpack.config.js. You'll need to add loaders, which will look something like...
module.exports = {
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loaders: 'babel', query: { presets: ['react', 'es2015', 'stage-1'] } },
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
},
...
}
Finally, make sure you have a resolution rule for CSS in webpack.config.js...
resolve: {
extensions: ['', '.js', '.css',...]
}

How to enable SASS Modules in Webpack 4

In my Node React web application written in TypeScript and TSX, I make use of CSS modules. Hence, when building the application I instruct Webpack to create a style.css.d.ts file out of a style.css so that I can access its classes like any other param by importing the CSS file into the TypeScript class with import * as style from "./style.css"; and then access the params like this:
export class Foot extends React.Component<FootProps, {}> {
render() {
return <div className={style.foot}>© MySite</div>;
}
}
What I'd like to do now is change from CSS to the SASS format SCSS and basically do the same thing. I want to have my SASS file i.e. style.scss and instruct Webpack to create a style.scss.d.ts file at build time. Though I can't figure out how to do that.
Module rule in my webpack.config.js:
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
{ test: /\.css$/, use: [
"style-loader",
{ loader: "typings-for-css-modules-loader", options: { modules: true, namedExport: true, camelCase: true, localIdentName: "[name]_[local]_[hash:base64]" }}
] },
{ test: /\.(scss)$/, use : [
{
// Adds CSS to the DOM by injecting a `<style>` tag.
loader: "style-loader"
},
{
// Interprets `#import` and `url()` like `import/require()` and will resolve them.
loader: "css-loader"
},
{
// Loader for webpack to process CSS with PostCSS.
loader: "postcss-loader",
options: {
plugins: function () {
return [
require("autoprefixer")
];
}
}
},
{
// Loads a SASS/SCSS file and compiles it to CSS.
loader: "sass-loader"
}
]
}
]
},
Dependencies in my package.json:
"dependencies": {
"#types/jquery": "^3.3.22",
"#types/react": "^16.4.18",
"#types/react-dom": "^16.0.9",
"bootstrap": "^4.1.3",
"jquery": "^3.3.1",
"popper.js": "^1.14.4",
"react": "^16.6.0",
"react-dom": "^16.6.0"
},
"devDependencies": {
"autoprefixer": "^9.3.1",
"awesome-typescript-loader": "^5.2.1",
"css-loader": "^1.0.1",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.10.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^7.1.0",
"source-map-loader": "^0.2.4",
"style-loader": "^0.23.1",
"typescript": "^3.1.6",
"typings-for-css-modules-loader": "^1.7.0",
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
}
What must I do to change from CSS modules to SASS Modules?
I found it out myself. So, I post it here in hope to help you guys if you have the same problem - +1 like if it did help ;).
I had to pay attention to a Bootstrap SCSS import, so I had to use Webpack's exclude and include functionality for differentiating between local and global CSS imports. Everything works fine now and these are my new module rules within my webpack.config.js file:
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "typings-for-css-modules-loader", options: { modules: true, namedExport: true, camelCase: true, localIdentName: "[name]_[local]_[hash:base64]" }}
]
},
{
test: /\.scss$/,
exclude: /\.global.scss$/,
use : [
{ loader: "style-loader" },
{ loader: "typings-for-css-modules-loader", options: { modules: true, namedExport: true, camelCase: true, localIdentName: "[name]_[local]_[hash:base64]" }},
{ loader: "postcss-loader", options: { plugins: function () { return [ require("autoprefixer") ]; }}},
{ loader: "sass-loader" }
]
},
{
test: /\.scss$/,
include: /\.global.scss$/,
use : [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "postcss-loader", options: { plugins: function () { return [ require("autoprefixer") ]; }}},
{ loader: "sass-loader" }
]
}
I can't find any flaw in your rules.Better try the following:
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: IS_DEV
}
}
]
},
{
test: /\.(scss)$/,
use: [
{
// Adds CSS to the DOM by injecting a `<style>` tag
loader: 'style-loader'
},
{
// Interprets `#import` and `url()` like `import/require()` and will resolve them
loader: 'css-loader'
},
{
// Loader for webpack to process CSS with PostCSS
loader: 'postcss-loader',
options: {
plugins() {
return [
require('autoprefixer')
];
}
}
},
{
// Loads a SASS/SCSS file and compiles it to CSS
loader: 'sass-loader'
}
]
}
This works for me.

Webpack not compiling scss to css

I'm building an app using webpack, babel, and Sass. Everything working fine but sass file not compiling css file even though it's not throwing any errors.
My Packages related to this are:
"webpack": "^3.10.0",
"css-loader": "^0.28.9",
"extract-text-webpack-plugin": "^3.0.2",
"glob-all": "^3.1.0",
"node-sass": "^4.7.2",
"purify-css": "^1.2.5",
"purifycss-webpack": "^0.7.0",
"sass-loader": "^6.0.6"
webpack.config.js:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const glob = require('glob-all');
var PurifyCSSPlugin= require('purifycss-webpack');
module.exports = {
entry: './src/js/index.js',
output: {
path: __dirname,
filename: 'dist/js/bundle.js'
},
watch: true,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env', 'stage-3'],
}
}
},
{
test:/\.css$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
url: false
}
}
]
})
},
{
test:/\.scss$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
url: false
}
},
'sass-loader'
]
})
}
]
},
plugins: [
new ExtractTextPlugin({
filename: './dist/css/styles.css'
}),
new PurifyCSSPlugin({
paths: glob.sync([
path.join(__dirname, 'dist/index.html'),
path.join(__dirname, 'src/js/*.js')
])
})
]
}
Files Directory:
This is my project Files Directory
test:/\.scss$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: ['style-loader', 'css-loader', 'sass-loader']
options: {
url: false
}
},
]
})

How to add CSS configuration in reactjs Project?

I've written the webpackconfig but css doesn't seem to work properly and it is throwing and error. Following are my file's contains.
My webpack.config.js:
module: {
loaders: [
{
test: /\.js?/,
include: SRC_DIR,
loader: "babel-loader",
query: {
presets: ["react", "es2015", "stage-2"]
}
}
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
}
{
test: /\.less$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
}
]
},
plugins: [
new ExtractTextPlugin("style.css", {
allChunks: true
})
]
};
and in my Index.js I've added as :
import '../assets/css/style.css';
Package.json :
{
...
"dependencies": {...
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.3",
"css-loader": "^0.28.7",
"style-loader": "^0.19.0"
}
}
As per our chat, this is what your webpack.config.js file is as below:
var path = require("path");
var DIST_DIR = path.resolve(__dirname, "dist");
var SRC_DIR = path.resolve(__dirname, "src");
var config = {
entry: SRC_DIR + "/app/index.js",
output: {
path: DIST_DIR + "/app",
filename: "bundle.js",
publicPath: "/app/"
},
module: {
loaders: [
{
test: /\.js?/,
include: SRC_DIR,
loader: "babel-loader",
query: {
presets: ["react", "es2015", "stage-2"]
}
}
{
test: /\.css$/,
loaders: ["style-loader", "css-loader", "sass-loader"]
}
{
test: /\.less$/,
loader: ExtractTextPlugin.extract("css-loader!sass-loader")
}
]
},
plugins: [
new ExtractTextPlugin("src/components/assets/css/style.css", {
allChunks: true
})
]
};
module.exports = config;
There are two issues with this config.
The are no commas separating the loaders objects.
You are using ExtractTextPlugin but have not imported/required it anywhere in the config.
Issue #1 is quite obvious how to solve; simply add the commas after each definition of a loader object.
Issue #2 as well, you need to install and reference ExtractTextPlugin in you webpack config file.
You can do so by running the following command in your terminal:
npm install --save-dev extract-text-webpack-plugin
This will install the plugin to your node_modules and also list it in your package.json file under thedevDependencies` object.
And then in your webpack.config.js where you are requiring modules, also require the plugin like so:
const ExtractTextPlugin = require("extract-text-webpack-plugin");
After making these changes, you config file should look something like this:
var path = require("path");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var DIST_DIR = path.resolve(__dirname, "dist");
var SRC_DIR = path.resolve(__dirname, "src");
var config = {
entry: SRC_DIR + "/app/index.js",
output: {
path: DIST_DIR + "/app",
filename: "bundle.js",
publicPath: "/app/"
},
module: {
loaders: [
{
test: /\.js?/,
include: SRC_DIR,
loader: "babel-loader",
query: {
presets: ["react", "es2015", "stage-2"]
}
},
{
test: /\.css$/,
loaders: ["style-loader", "css-loader", "sass-loader"]
},
{
test: /\.less$/,
loader: ExtractTextPlugin.extract("css-loader!sass-loader")
}
]
},
plugins: [
new ExtractTextPlugin("src/components/assets/css/style.css", {
allChunks: true
})
]
};
module.exports = config;

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