Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

the-style-processing-of-webpack #11

Open
Akiq2016 opened this issue Jan 13, 2018 · 9 comments
Open

the-style-processing-of-webpack #11

Akiq2016 opened this issue Jan 13, 2018 · 9 comments
Labels

Comments

@Akiq2016
Copy link
Owner

Akiq2016 commented Jan 13, 2018

style-loader

Adds CSS to the DOM by injecting a <style> tag

css-loader

The css-loader interprets @import and url() like import/require() and will resolve them.

Sets importLoaders option to prevent some bugs like: @imported files do not get processed by postcss's autoprefixer. postcss-loader#35 (Solution2: uses postcss-import plugin before autoprefixer)

Sets minimize option to minimize the css files.

postcss-loader

Loader for webpack to process CSS with PostCSS. Use it after css-loader and style-loader, but before other preprocessor loaders like e.g sass|less|stylus-loader, if you use any. Remember to set up postcss.config.js file too.

The Autoprefixer PostCSS plugin is one of the most popular CSS processors. (cssnano is great too. !)

sass-loader

Loads a SASS/SCSS file and compiles it to CSS. The sass-loader requires node-sass and webpack as peerDependency.

To enable CSS source maps, pass the sourceMap option to the sass-loader and the css-loader.

When you use preprocessor loaders with its option sourceMap being set, don't omit the sourceMap option in postcss-loader(if you have this loader), or the previous source maps will be discarded by postcss-loader entirely.

That's said, if you want to enable css's source maps function, ensure the relavant style's loaders have set the sourceMap option. you also need to include devtool option for webpack too. sass-loader#7

ExtractTextWebpackPlugin

Extract text from a bundle, or bundles, into a separate file.

new ExtractTextPlugin(options: filename | object)

As the following example, it moves all the required *.scss modules in entry chunks into a separate CSS file. So your styles are no longer inlined into the JS bundle, but in a separate CSS file main.css. If your total stylesheet volume is big, it will be faster because the CSS bundle is loaded in parallel to the JS bundle.

// webpack.config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = {
  entry: {
    main: path.resolve(__dirname, '../src/index.js')
  },
  devtool: 'eval-source-map' // for development mode
  module: {
    rules: [{
      test: /\.scss$/,
      use: ExtractTextPlugin.extract({
        fallback: 'style-loader',
        use: [
          {
            loader: 'css-loader',
            options: { importLoaders: 2, minimize: true, sourceMap: true },
          },
          {
            loader: 'postcss-loader',
            options: { sourceMap: true },
          },
          {
            loader: 'sass-loader',
            options: { sourceMap: true },
          },
        ]
      })
    }]
  },
  plugins: [
    new ExtractTextPlugin({ filename: '[name].css' })
  ]
}
@yola-0316
Copy link

Awesome!

@Akiq2016
Copy link
Owner Author

Akiq2016 commented Feb 2, 2018

CSS background URL solutions

  • Use ExtractTextWebpackPlugin 's option publicPath to set publicPath for CSS.
  • Set resolve.alias property in webpack.

vue-loader#481
css-loader#256

@Akiq2016
Copy link
Owner Author

Akiq2016 commented May 2, 2018

ExtractTextPlugin

Only use ExtractTextPlugin in production mode. It haven't supported HMR yet. But ensure to use NODE_ENV instead of setting --mode in cli.

NODE_ENV not set on process.env
Expose the mode option for loaders

@shanesstudying
Copy link

@Akiq2016
Copy link
Owner Author

Interesting.. I haven't used this loader before. So I misunderstand its usage too at first glance. lemme add some note here.

resolve-url-loader

Webpack css-loader will get assets out of url() statements. That is not what this loader does.

This loader sits before css-loader and rewrites url() paths before they get to css-loader.

Imagine you have a url() relative a scss file, which itself is imported into another scss file. Webpack will only see the root scss file and expect the asset to be relative to it. It will never know there was a nested scss file. It will go looking for the assets relative tot he root scss file and not find them.

This loader looks in the source-map and finds the original file where the url() statement resides. It can then rewrite the path so that css-loader will be able to find the asset.

Originally I wrote this loader because I had a root scss file for the project, and feature-based scss files and assets in a number of directories.

Conversely if you have all your assets centralised then this is not your use-case.

resolve-url-loader#51

@shanesstudying
Copy link

shanesstudying commented Jun 8, 2018

In the end I used all these for CSS:

// CSS
{
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: [
            {
              //loader: "css-loader",
              loader: "typings-for-css-modules-loader",
              options: {
                importLoaders: 2,
                minimize: true,
                sourceMap: true,
                modules: true,
                localIdentName: "[name]_[local]_[hash:base64:5]",
                namedExport: true
              }
            },
            {
              loader: "postcss-loader",
              options: { sourceMap: true }
            },
            {
              loader: "resolve-url-loader",
              options: { sourceMap: true }
            },
            {
              loader: "sass-loader",
              options: { sourceMap: true }
            }
          ]
        })
      },

This was effective for all the following:

  • Separate CSS files locally for each component in 'src'
  • Bundling into one CSS file in 'dist'
  • CSS is minimised in 'dist'
  • CSS is perfectly source-mapped for readable debugging
  • CSS file in dist is hashed and hash alters in accordance with changes saved
  • Class names simple and local in 'src'
  • Class names altered as per CSS modules to maintain local scope
  • Background image loaded via CSS as such:
          background: url("../images/cliff.jpg") no-repeat fixed center;
          background-size: cover;
  • CSS urls working for importing other CSS files and font-face declaration CSS files as such:
          @import url("./another.scss");
          @import url("../fonts/Darkenstone/ff_Darkenstone.css");
  • Custom fonts stored locally, declared in @font-face, are loaded via url-loader
  • PostCSS is enabled, though I've only used it for autoprefixer so far
  • Source is written in TypeScript, imports into TS files work
  • SCSS works

I'm interested in what else there is to do for CSS ... this was a lot of processing for webpack to get through... apparently the community have discovered a lot of problems with CSS that needed fixing....

Your original post got me through to achieve the vast majority of my CSS goals.
Thankyou very much :) as this was a headache for ages.

@Akiq2016
Copy link
Owner Author

Akiq2016 commented Jun 8, 2018

:D I'm so glad to help you! Feel free to discuss any tech stuff in my issue, I'd like to learn together! 👯
Anyway, how you handle hmr with css? As you use extraTextPlugin directly without setting disalbe option in development mode? Some related repo: css-hot-loader

@shanesstudying
Copy link

Haven't properly evaluated HMR in production, just using DevServer for development, CSS changes work fine.
Next step was incorporating it into SPA Services with an ASP.Net back end.
And the big goal... server pre-rendering.

@Akiq2016
Copy link
Owner Author

Akiq2016 commented Jun 9, 2018

if you use react, check next :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants