webpack-contrib / extract-text-webpack-plugin

[DEPRECATED] Please use https://github.com/webpack-contrib/mini-css-extract-plugin Extracts text from a bundle into a separate file
MIT License
4.01k stars 513 forks source link

Syntax should be updated to new webpack loaders syntax? #265

Closed wlingke closed 7 years ago

wlingke commented 7 years ago

Syntax here should be updated too?

https://github.com/webpack/webpack.js.org/blob/develop/content/how-to/upgrade-from-webpack-1.md#moduleloaders-is-now-modulerules

bfricka commented 7 years ago

Definitely. It should also follow the pattern of use: [], so we should be able to convert:

const extractCSS = new ExtractTextPlugin(/*...*/);

module.exports = () => {
  return {
    postcss: {plugins: [autoprefixer(autoprefixerOpts)], sourceMap: true},
    loaders: [
      {test: /\.scss/i, loader: extractCSS.extract(['css?sourceMap', 'postcss', 'sass?sourceMap'])}
    ]
  };
};

to the new use + options syntax:

const extractCSS = new ExtractTextPlugin(/*...*/);
const postcssOpts = postcss: {plugins: [autoprefixer(autoprefixerOpts)], sourceMap: true};

module.exports = () => {
  return {
    rules: [
      {test: /\.scss/i, use: [
        extractCSS.extract([  // This is basically "use"
          {loader: 'css', options: {sourceMap: true}}
          {loader: 'postcss', options: postcssOpts}
          {loader: 'sass', options: {sourceMap: true}
        ])     
      ]}
    ]
  };
};

This seems like the right approach unless the new "rules" syntax allows extract-text-webpack-plugin to somehow work as the first item in the "use" array. I haven't looked at the source yet to see how this might work, but it seems unlikely.

wlingke commented 7 years ago

Doesn't seem like it works yet, but hopefully they will update it soon to match with the new webpack2 beta25

jhnns commented 7 years ago

Yes, I agree. This could be very frustrating for users when migrating to webpack 2.

dsebastien commented 7 years ago

Hello,

I'm currently trying to figure out how i can configure this plugin with post-css like I did with Webpack 1.x. Is this supposed to work already in some form?

Here's what I have configured for now and that isn't working (which I guess is due to this very issue :p):

// Support for PostCSS
            {
                test: /\.scss$/,
                use: ExtractTextWebpackPlugin.extract({
                    fallbackLoader: "style-loader",
                    loader: [
                        {
                            loader: "css-loader",
                            query: {
                                modules: true, // to check if needed
                                sourceMap: true,
                            },
                        },
                        {
                            loader: "postcss-loader",
                            options: {
                                sourceMap: true,
                                plugins: () => commonData.postcss,
                            },
                        },
                    ],
                }),
            },

Where commonData.postcss is:

postcss: [
        // reference: https://github.com/postcss/postcss-import
        // https://github.com/postcss/postcss-import/issues/244
        require("postcss-import")(),

        // plugin to rebase, inline or copy on url().
        // https://github.com/postcss/postcss-url
        require("postcss-url")(),

        require('postcss-nesting')(),
        require('postcss-simple-extend')(),
        require("postcss-cssnext")({
            browsers: [ "last 3 versions" ]
        })
    ],

The above gives me the following errors:

ERROR in ./src/app/css/vendor.scss
Module parse failed: C:\LocalData\DEV\Workspace\AAH-Stark\node_modules\extract-text-webpack-plugin\loader.js?{"omit":1,"remove":true}!style-loader!css-loader?{"modules":true,"sourceMap":true}!postcss-loader!C:\LocalData\DEV\Workspace\AAH-Stark\node_modules\extract-text-webpack-plugin\loader.js?{"omit":1,"remove":true}!style-loader!css-loader?{"modules":true,"sourceMap":true}!postcss-loader!C:\LocalData\DEV\Workspace\AAH-Stark\src\app\css\vendor.scss Unexpected character '@' (8:0)
You may need an appropriate loader to handle this file type.
| 
| @import "../../../node_modules/angular-material-steppers/dest/angular-material-steppers.css";
| 

Can I change this somehow for now and get it working?

renarsvilnis commented 7 years ago

@dsebastien This is my production webpack config entries only for scss I got set up few days ago. Only thing is that sourceMaps get always generated, even if I don't want to.

{
  test: /\.(scss)$/i,
  // using "loader" instead of newer "use"
  loader: ExtractTextPlugin.extract({
    loader: [
      {
        loader: 'css-loader',
        // current extract-text-plugin supports query not never options format
        query: {
          importLoaders: 3,
          minimize: true,
          // Even if disabled sourceMaps gets generated
          sourceMap: false
        }
      },
      {loader: 'postcss-loader'},
      {loader: 'resolve-url-loader'},
      {
        loader: 'sass-loader',
        query: {
          // Enable sourcemaps for resolve-url-loader to work properly
          sourceMap: true
        }
      }
    ]
  })
}
plugins: [
  /**
   * LoaderOptionsPlugin is used for aid migrationfor older loaders
   * @reference https://github.com/webpack/webpack.js.org/blob/develop/content/how-to/upgrade-from-webpack-1.md#loaderoptionplugin-context
   */
  new webpack.LoaderOptionsPlugin({
    minimize: true,
    debug: false,
    options: {
      /**
       * resolve-url-loader fix
       * @reference https://github.com/bholloway/resolve-url-loader/issues/33#issuecomment-249830601
       */
      context: path.join(__dirname, 'src'),
      output: {
        path: path.join(__dirname, 'dist')
      },
      /**
       * Legacy postCSS config
       * @reference https://github.com/azat-io/webpack2-css-modules-demo/blob/master/scripts/webpack.config.babel.js
       */
      postcss: [
        require('autoprefixer')({
          browsers: ['last 2 versions', 'IE > 10'],
          cascade: true,
          remove: true
        }),
        require('css-mqpacker')()
      ]
    }
  }),
  new ExtractTextPlugin({
    filename: '[name].css',
    allChunks: true
  })
]
dsebastien commented 7 years ago

Thanks @renarsvilnis , seems to be working! On to the next issue now :D

quantuminformation commented 7 years ago

I previously used

    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: PATHS.src
      },
      {
        test: /\.pcss$/,
        loaders: [
          'style-loader',
          'css-loader?importLoaders=1',
          'postcss-loader'
        ]
      },
      {
        test: /\.css$/,
        loaders: [
          'style-loader',
          'css-loader'
        ]
      }
    ]

What should I use now if I want to extract all my styles using the ExtractTextPlugin?

kellyrmilligan commented 7 years ago

this was frustrating to me, I was trying to be more up to date on the syntax and it failed! glad I found this.

mlcohen commented 7 years ago

I ran into this exact problem using webpack2 (v2.2.0-rc.1) when trying apply the StringReplacePlugin (https://github.com/jamesandersen/string-replace-webpack-plugin/issues/20). Is it intentional that for plugins like ExtractTextPlugin and StringReplacePlugin that they use the loader module rule syntax over the new use syntax? If so, it would really help to clarify why that is, otherwise it would be helpful if webpack2 went with one approach.

domeknn commented 7 years ago

@QuantumInformation I am using this for production.


loader: ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: [
            'css?modules&importLoaders=1&localIdentName=[path][name]__[local]___[hash:base64:5]',
            'postcss-loader'
          ]
        })
quantuminformation commented 7 years ago

@domeknn way too cryptic for me mate ;)

tmair commented 7 years ago

I came across this issue today when I tried to upgrade to webpack2. For me the following change (https://github.com/tmair/extract-text-webpack-plugin/commit/1414036c9fcacb441ce8d89eebb618a46a48de51) fixed the issue I was having, I am just not sure if it is the correct fix for the issues I am experiencing

felixsanz commented 7 years ago

@jhnns

Yes, unfortunately the extract-text-webpack-plugin hasn't caught up with the new loader configuration of webpack 2. We need to solve that before releasing webpack 2.

webpack 2 is in release candidate and this is still not fixed. Just a friendly reminder!

Emobe commented 7 years ago

Using the fix provided by @tmair works perfect for me at the moment. been scratching my head all day with this when migrating

insin commented 7 years ago

Using @tmair's change to return loader objects from ExtractTextPlugin.extract() instead of stringifying allows me to use use config with ExtractTextPlugin and combined with ident (thanks to @bebraw in the Slack channel) makes this sort of config work:

Don't quote me on the correctness of this exact rule config, I'm using nwb to generate config and manually reconstructed the below to share the approach.

See nwb output
rules: [{
  test: /\.styl$/,
  use: ExtractTextPlugin.extract({
    fallbackLoader: {loader: 'style-loader'},
    loader: [
      {
        loader: 'css-loader',
        options: {
          importLoaders: 1
        }
      },
      {
        loader: 'postcss-loader',
        options: {
          plugins: [autoprefixer()]
        }
      },
      {
        loader: 'stylus-loader',
        options: {
          use: [nib()],
          import: ['~nib/lib/nib/index.styl']
        }
      }
    ]
  })
}]

Edit: as of Webpack 2.2.1 you don't need to use ident either - options should be passed as-is to each loader.

Rincewind3d commented 7 years ago
module: {
    loaders: [
        {
            test: /\.scss$/,
            loader: ExtractTextPlugin.extract(['style-loader', 'css-loader?sourceMap!resolve-url-loader!sass-loader?sourceMap'])
        },
        {
            test: /\.css$/,
                loader: ExtractTextPlugin.extract(['style-loader', 'css-loader?sourceMap!resolve-url-loader'])
        },
    ],
}

leads to

 ERROR in ./~/bootstrap-sass/assets/stylesheets/_bootstrap.scss
    Module parse failed: /foobar/node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss Unexpected character '@' (8:0)
    You may need an appropriate loader to handle this file type.
    | 
    | // Core variables and mixins
    | @import "bootstrap/variables";
    | @import "bootstrap/mixins";
    | 
     @ ./src/entries/basic.js 6:0-60
mobilesite commented 7 years ago

I can now get through with this:

  1. dependencies in package.json
"devDependencies": {
    "autoprefixer": "^6.6.1",
    "babel-core": "^6.22.1",
    "babel-loader": "^6.2.10",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-es2015-webpack": "^6.4.3",
    "clean-webpack-plugin": "^0.1.15",
    "css-loader": "^0.26.1",
    "extract-text-webpack-plugin": "^2.0.0-beta.5",
    "html-webpack-plugin": "^2.26.0",
    "less": "^2.7.2",
    "less-loader": "^2.2.3",
    "node-sass": "^4.3.0",
    "open-browser-webpack-plugin": "0.0.3",
    "path": "^0.12.7",
    "postcss-loader": "^1.2.2",
    "sass-loader": "^4.1.1",
    "style-loader": "^0.13.1",
    "webpack": "^2.2.0",
    "webpack-dev-server": "^2.2.0"
  }
  1. some code in webpack.config.dev.js
var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');

var path = require('path');
var resolvePath = path.resolve;
var joinPath = path.join;
var rootPath = resolvePath(__dirname, '../');
var srcPath = joinPath(rootPath, 'src');
var postcssConfigPath = joinPath(rootPath, 'config/postcss.config.js');
            {
                test: /\.less$/,
                loader: ExtractTextWebpackPlugin.extract({ 
                    fallbackLoader: 'style-loader',
                    loader: [
                        {
                            loader: 'css-loader',
                            query: {
                                sourceMaps: true,
                                modules: true,
                                importLoaders: 1,
                                localIdentName: '[hash:base64:5]'
                            }
                        },
                        {
                            loader: 'postcss-loader',
                            query: {
                                config: postcssConfigPath
                            }
                        },
                        'less-loader'
                    ]
                }), 
                include: srcPath
            }
  1. postcss.config.js
    module.exports = {
    plugins: [
        require('autoprefixer')
    ]
    }
Rincewind3d commented 7 years ago

Hm... could it be that there is an issue with the sass-loader?

module: {
    loaders: [
        {
            test: /\.scss$/,
            loader: ExtractTextPlugin.extract({
                    fallbackLoader: 'style-loader',
                    loader: [{
                        loader: 'css-loader',
                        query: {
                            sourceMaps: true
                        }
                    }, {
                        loader: 'resolve-url-loader'
                    }, {
                        loader: 'sass-loader',
                        query: {
                            sourceMaps: true
                        }
                    }]
                })
        }, {
            test: /\.css/,
            loader: ExtractTextPlugin.extract({
                    fallbackLoader: 'style-loader',
                    loader: [{
                        loader: 'css-loader',
                        query: {
                            sourceMaps: true
                        }
                    }, {
                        loader: 'resolve-url-loader'
                    }]
                })
        }
    ],
  "dependencies": {
    "css-loader": "^0.26.1",
    "extract-text-webpack-plugin": "2.0.0-beta.5",
    "node-sass": "^3.4.2",
    "resolve-url-loader": "^1.4.3",
    "sass-loader": "^4.1.1",
    "style-loader": "^0.13.0",
    "webpack": "^2.2.0"
  },
 ERROR in ./~/bootstrap-sass/assets/stylesheets/_bootstrap.scss
    Module parse failed: /narf/node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss Unexpected character '@' (8:0)
    You may need an appropriate loader to handle this file type.
    | 
    | // Core variables and mixins
    | @import "bootstrap/variables";
    | @import "bootstrap/mixins";
    | 
     @ ./src/entries/basic.js 6:0-60
khankuan commented 7 years ago

Hmm it seems like the loader/string query syntax works but the use/js syntax doesn't. @michael-ciniawsky do you know if someone is already working on it? I would like to help but the status of the upgrade to webpack2 is unclear :/

michael-ciniawsky commented 7 years ago

@khankuan Yes this PR #343 should fix the syntax changes, not 💯 sure if thats everything to it but looks promising so far 😛

khankuan commented 7 years ago

Ah nice, i've just tested it with my project, works great!

joshwiens commented 7 years ago

Resolved with https://github.com/webpack-contrib/extract-text-webpack-plugin/releases/tag/v2.0.0-rc.0 & published to npm.

maxired commented 7 years ago

@d3viant0ne I can confirm this worked with webpack 2.2.0. ( was not with wepack 2.1.0-beta.26)

sylvesteraswin commented 7 years ago

I have been breaking my head to fix this issue and I can confirm this format worked

{
    test: /\.less$/,
    loader: stripExtract.extract(['css-loader', 'less-loader']),
}, {
    test: /\.css$/,
    loader: stripExtract.extract(['css-loader']),
},
thallada commented 7 years ago

Can someone add an example to the README on how to specify options to a loader in the list of loaders passed to the ExtractTextPlugin in webpack 2+? I'm still not clear on the syntax ("use" vs. "loader" and "options" vs. "query").

khankuan commented 7 years ago

@thallada i've tried the following with success:

const loader = [
   'css-loader',
   'postcss-loader',
 ];
...
{
  test: /\.css/,
  include: [
    path.resolve('./src'),
  ],
  loader: production ? ExtractTextPlugin.extract({
    loader,
  }) : undefined,
  use: production ? undefined : ['style-loader', ...loader],
}
joshwiens commented 7 years ago

@thallada - Could you please open a new issue so this can get properly documented as there is an obvious gap. Your requests stands a really good chance of getting lost in the black hole that is old / closed issues.

K1pavic commented 7 years ago

Hello, I'm too fighting with webpack 2 the past couple of days. I'm new to webpack, so it's even more fun :).

I've made an webpack 2 starter pack which I want to use in the future (angular, bootstrap, sass etc.). It is working fine (after some learning by trial and error and then some more of the same) I made a push into my github repo. After that, just to make sure everything works I cloned (couple minutes later) the same repo, ran npm instal and webpack and got this error:

loader option has been deprecated - replace with "use"
E:\test\Webpack-starter\node_modules\extract-text-webpack-plugin\schema\vali
dator.js:11
                throw new Error(ajv.errorsText());
                ^

Error: data['fallbackloader'] should NOT have additional properties
    at validate (E:\test\Webpack-starter\node_modules\extract-text-webpack-p
lugin\schema\validator.js:11:9)
    at Function.ExtractTextPlugin.extract (E:\test\Webpack-starter\node_modu
les\extract-text-webpack-plugin\index.js:196:3)

I checked everything, I'm running the same node, npm and webpack version, and everything else is the same. So I now have two identical webpack projects, from which one isn't working. But, there is more. After I cloned the repo and got the error I changed something in my webpack.config.js file and now I have two webpack projects, where the config isn't the same, but both are running without errors. To create the same webpack.config.js file for both projects isn't possible.

The first webpack.config.js file (I created locally)

module: {
        loaders: [{
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract({
                    loader: "css-loader?minimize!postcss-loader!sass-loader",
                    fallbackloader: "style-loader"
                })
            },...

The second `webpack.config.js`` file (I cloned from github)

module: {
        loaders: [{
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract({
                    use: "css-loader?minimize!postcss-loader!sass-loader",
                    fallback: "style-loader"
                })
            },...

If I try and rewrite the first webpack.config.js so it matches the second one I get this error:

E:\webpack2\node_modules\extract-text-webpack-plugin\index.js:134
        if(!loader.query) return loader.loader;
                  ^

TypeError: Cannot read property 'query' of undefined
    at getLoaderWithQuery (E:\webpack2\node_modules\extract-text-webpack
-plugin\index.js:134:12)
    at Array.map (native)

I'm working with webpack the past 3 days, so I'm all the time at the newest version of webpack 2.2.1. Hope this will help resolving this issue.

khankuan commented 7 years ago

@K1pavic i think you might want to use the json syntax rather than the string syntax:

"css-loader?minimize!postcss-loader!sass-loader"

into:

[{
  loader: 'css-loader',
  options: {
    minimize: true,
  },
},
'postcss-loader',
'sass-loader'
]
chocobuckle commented 7 years ago

I can't for the life of me work out why this config isn't working. I've read through all this thread (and many others!) but no joy. My config for ExtractTextPlugin is using the recommended syntax as far as I can see, but still not giving me any results. Any help would be much appreciated! :)

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

module.exports = {
  entry: './dev/js/index.js',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js',
  },
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            {
              loader: 'css-loader',
              options: {
                import: false,
                importLoaders: 1,
                minimize: false,
                sourceMap: true,
                url: false,
              },
            },
            {
              loader: 'postcss-loader',
              options: {
                sourceMap: true,
              },
            },
          ],
        }),
      },
    ],
  },
  plugins: [
    new ExtractTextPlugin('styles.css'),
  ],
};
module.exports = {
  plugins: {
    'postcss-import': {},
    'postcss-simple-vars': {},
    'postcss-nested': {},
    autoprefixer: {},
    cssnano: {},
  },
};
K1pavic commented 7 years ago

Hello, I don't have much time at the moment, tommorow will be better, but what I saw at the first glance ist that you miss some stuff in the ExtractTextPlugin format, like this: plugins: [ new ExtractTextPlugin({ filename: "bundle.css" }),

]For more examples you can use my working tempalte at https://github.com/K1pavic/Webpack-starter

Hope it helps. Kristian

2017-06-25 17:57 GMT+02:00 Conor Doyle notifications@github.com:

I can't for the life of me work out why this config isn't working. I've read through all this thread (any many others!) but no joy. My config for ExtractTextPlugin is using the recommended syntax as far as I can see, but still not giving me any results. Any help would be much appreciated! :)

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

module.exports = { entry: './dev/js/index.js', output: { path: path.resolve(__dirname, 'build'), filename: 'bundle.js', }, devtool: 'source-map', module: { rules: [ { test: /.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: [ { loader: 'css-loader', options: { import: false, importLoaders: 1, minimize: false, sourceMap: true, url: false, }, }, { loader: 'postcss-loader', options: { sourceMap: true, }, }, ], }), }, ], }, plugins: [ new ExtractTextPlugin('styles.css'), ], };

— 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/265#issuecomment-310911010, or mute the thread https://github.com/notifications/unsubscribe-auth/AKwP26qhRGwPapo9zEIpM62AjoDMQr1aks5sHoNSgaJpZM4KQkJc .

-- Kristian Pavić, MSc in Computer Science Faculty of Electrical Engineering Osijek

Phone:+4915255793267 E-mail: k1pavic@gmail.com k1pavic@gmail.com

chocobuckle commented 7 years ago

@K1pavic Greatly appreciate your help on a Sunday Kristian, but ExtractTextPlugin now takes either an object or the name of the result file. So...

  plugins: [
    new ExtractTextPlugin({
      filename: 'styles.css'
    })
  ]

is equivalent to...

  plugins: [
    new ExtractTextPlugin('styles.css')
  ]

...so that's not the problem. Guess I'll keep hacking about and hopefully figure it out eventually - story of my life! :)

K1pavic commented 7 years ago

Glad to help :)

Like I said, you can try and use the project I put on Github, there everything should work just fine. You can remove the angular and bootstrap stuff if you don't need it.

If you don't make any progress to monday afternoon I can take a better look.

Good luck Kristian

2017-06-25 18:55 GMT+02:00 Conor Doyle notifications@github.com:

@K1pavic https://github.com/k1pavic Greatly appreciate your help on a Sunday Kristian, but ExtractTextPlugin now takes either an object or the name of the result file. So...

plugins: [ new ExtractTextPlugin({ filename: 'styles.css' }) ]

is equivalent to...

plugins: [ new ExtractTextPlugin('styles.css') ]

...so that's not the problem. Guess I'll keep hacking about and hopefully figure it out eventually - story of my life! :)

— 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/265#issuecomment-310914144, or mute the thread https://github.com/notifications/unsubscribe-auth/AKwP24V-3F_Ky4Ht7YKhYDK1LwaLmfSQks5sHpDxgaJpZM4KQkJc .

-- Kristian Pavić, MSc in Computer Science Faculty of Electrical Engineering Osijek

Phone:+4915255793267 E-mail: k1pavic@gmail.com k1pavic@gmail.com