Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting css output using webpack ExtractTextPlugin

Tags:

webpack

I am trying to get css requires to work in webpack using the ExtractTextPlugin but with no success

I want a separate css file rather than inlining any css.

Here is my webpack config:

var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './scripts/index'
  ],
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath: '/scripts/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new ExtractTextPlugin('styles/styles.css', {
      allChunks: true
    })
  ],
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  module: {
    loaders: [{
      test: /\.jsx?$/,
      loaders: ['react-hot', 'babel'],
      include: path.join(__dirname, 'scripts')
    },
    {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
    }]
  }
};

index.js:

import React from 'react';
import App from './App';

React.render(<App />, document.getElementById('root'));

App.js:

import React from 'react';

require('../styles/app.css');

export default class App extends React.Component {
  render() {
    return (
      <h1>Hello, world.</h1>
    );
  }
}

index.html:

<html>
  <head>
    <link rel="stylesheet" href="/styles/styles.css">
  </head>
  <body>
    <div id='root'></div>
  </body>
  <script src="/scripts/bundle.js"></script>
</html>

styles.css is returning 404

Any idea what could be going wrong here. If I don't use the ExtractTextPlugin and just do this in config:

module: {
        loaders: [
            { test: /\.css$/, loader: "style-loader!css-loader" }
        ]
    }

then I get the css applied to the page correctly but obviously this is not coming from a css file

This is my first attempt at using webpack so probably doing some noob mistake

Any ideas?

like image 866
jamie holliday Avatar asked Apr 19 '15 13:04

jamie holliday


3 Answers

ExtractTextPlugin needs to be added in two spots: in the Loader, and as a Plugin. Here's the example pulled from the stylesheets documentation.

// webpack.config.js var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = {     // The standard entry point and output config     entry: {         posts: "./posts",         post: "./post",         about: "./about"     },     output: {         filename: "[name].js",         chunkFilename: "[id].js"     },     module: {         loaders: [             // Extract css files             {                 test: /\.css$/,                 loader: ExtractTextPlugin.extract("style-loader", "css-loader")             },             // Optionally extract less files             // or any other compile-to-css language             {                 test: /\.less$/,                 loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")             }             // You could also use other loaders the same way. I. e. the autoprefixer-loader         ]     },     // Use the plugin to specify the resulting filename (and add needed behavior to the compiler)     plugins: [         new ExtractTextPlugin("[name].css")     ] } 
like image 106
matpie Avatar answered Nov 12 '22 14:11

matpie


I have modified your config filenames and how you include them in page

   var path = require('path');
   var webpack = require('webpack');
   var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './scripts/index'
  ],
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'scripts/bundle.js',
    publicPath: '/scripts/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new ExtractTextPlugin('styles/styles.css', {
      publicPath: '/styles/',
      allChunks: true
    })
  ],
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  module: {
    loaders: [{
      test: /\.jsx?$/,
      loaders: ['react-hot', 'babel'],
      include: path.join(__dirname, 'scripts')
    },
    {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
    }]
  }
};

Following is the html page

<html>
  <head>
    <link rel="stylesheet" href="build/styles/styles.css">
  </head>
  <body>
    <div id='root'></div>
  </body>
  <script src="build/scripts/bundle.js"></script>
</html>
like image 42
Kishorevarma Avatar answered Nov 12 '22 15:11

Kishorevarma


Using css-loader and style-loader together first parse your CSS, then turn it into style nodes, which can be imported in Webpack just like code. I don't understand why you'd want this artificial relationship built between your JavaScript and your CSS.

The above approach emits CSS again in the end. Why put your code through a round trip like that? Use raw-loader and add your main CSS file to your entry points. You lose any error-checking that css-loader performs, but your compilation happens much faster. But if you're using something like sass-loader, you'll still get all the error checking.

like image 37
Nate Symer Avatar answered Nov 12 '22 15:11

Nate Symer