born2net
born2net

Reputation: 24953

How to include an external css file using Webpack and Angular2?

I am trying to add an external reference to a CSS file in Angular2 using Webpack. My css is defined as

{ test: /\.css$/, loader: "style-loader!css-loader" },

in my webpack.config.js file and I can load css just fine when doing in a head of a typescript file:

require("./styles/style.css");

However when I try and load a CSS file inline inside a component as in:

@Component({
selector: 'todo-list',
template: `
            <section class="todoapp">                 
            </section>
`,
styles: [require('./Todolist.css')], // <--------------
directives: [TodoItem],
providers: [TodosService]
...

I get an error of: EXCEPTION: TypeError: s.replace is not a function

I also tried to load CSS via:

styles: [require('style-loader!css-loader!./Todolist.css')]

but not much luck

any help is appreciated

regards

Sean

Upvotes: 8

Views: 23831

Answers (4)

Ramast
Ramast

Reputation: 7709

Modules you would need to install:

css-loader style-loader and optional but recommended url-loader

Changes to your webpack config (development) module: { loaders: [ // CSS { test: /\.css$/, loader: "style-loader!css-loader", }, /* rest of your loaders */ ]

In your main javascript file include your css file

import '../css/bootstrap.min.css';

Now in case of bootstrap in particular you will get errors like this:

ERROR in ./~/css-loader!./client/css/bootstrap.min.css Module not found: Error: Cannot resolve module 'url-loader' @ ./~/css-loader!./client/css/bootstrap.min.css 6:3278-3330 6:3348-3400

ERROR in ./~/css-loader!./client/css/bootstrap.min.css Module not found: Error: Cannot resolve module 'url-loader' @ ./~/css-loader!./client/css/bootstrap.min.css 6:3449-3503

ERROR in ./~/css-loader!./client/css/bootstrap.min.css Module not found: Error: Cannot resolve module 'url-loader' @ ./~/css-loader!./client/css/bootstrap.min.css 6:3533-3586

In that case u will need to download the mentioned files locally and add this entry to your webpack config (inside "loaders" section like the first one above)

{
    test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
    loader: 'url-loader',
    options: {
      limit: 10000
    }
}]

This is why u need to install url-loader package but it's only required if your css rely on other image/font files.

Note: Apparently for production use it's better to use a more complicated setup that involve ExtractTextPlugin mentioned by @squadwuschel

Here is all the details you might need https://webpack.github.io/docs/stylesheets.html

Upvotes: 0

squadwuschel
squadwuschel

Reputation: 3428

My current Solution for WebPack 2 with Angular 2 for css or scss Loader;

  {
      test: /\.css$/,
      loader: [
          ExtractTextPlugin.extract({ fallbackLoader: "style-loader", loader: 'css-loader' }),
          'to-string-loader',
          'css-loader'
      ],
      exclude: [helpers.root('Content')],
      include: [helpers.root('App')]
  },
  {
      test: /\.scss$/,
      loader: [ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: ['css-loader'] }),
          'to-string-loader',
          'css-loader',
          'sass-loader'
      ],
      exclude: [helpers.root('Content')],
      include: [helpers.root('App')]
  },

Plugins:

  new ExtractTextPlugin({ filename: "[name].css" }),

And now you can use the following in your component

@Component({
   selector: 'logmonitor',
   styleUrls: ['./logmonitor.component.scss', './logmonitor.component.css'],
   templateUrl: './logmonitor.component.html'
})

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"
 }

Update for Webpack 2.2.1 and extract-text-webpack-plugin 2.0.0-rc.3 here the solution above is not working any more.

addional devdependencies

"extract-text-webpack-plugin": "2.0.0-rc.3",
"postcss-loader": "1.3.0",
"postcss-import":  "9.1.0",
"autoprefixer": "6.7.2",
"webpack": "2.2.1",

you need to add a postcss.config.js in your root of your app with the content

module.exports = {
    plugins: [
         require('postcss-import')(),
         require('autoprefixer')()
    ]
};

and the new rule for scss is the following

{
    test: /\.scss$/,
    loader: [
        { loader: 'raw-loader' },
        { loader: 'sass-loader', query: { sourceMaps: true } },
        { loader: 'postcss-loader' }
    ],
    exclude: [helpers.root('Content')],
    include: [helpers.root('App')]
 }

Upvotes: 3

born2net
born2net

Reputation: 24953

What did the trick was to load css as raw text in the webpack.config.js

{
    test: /\.css$/,
    loader: 'raw!postcss'
},

regards

Upvotes: 6

Downhillski
Downhillski

Reputation: 2655

I have posted an answer for the similar question, I hope it will help with you to understand how the styles/styleUrls works in angular2. There is a piece of code I proved to append css to the application through your component.

Load external css style into Angular 2 Component

Upvotes: 1

Related Questions