webpack中css文件的代码分割

module.exports = {
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
    path: path.resolve(__dirname, '../dist')
  }
}

在看别人写的webpack,output配置项,肯跟会碰到chunkFilename这样的配置项,那这个是什么意思呢?filename和chunkFilename有什么区别呢?首先看个例子

index.html

<!DOCTYPE html>
<html >
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>html template</title>
  </head>
  <body>
    <div ></div>
  </body>
</html>

index.js

async function getComponent() {
  const { default: _ } = await import(/* webpackChunkName:'lodash' */'lodash');
  const element = document.createElement('div');
  element.innerHTML = _.join(['1', '2'], '-');
  return element
}

document.addEventListener('click', ()=> {
  getComponent().then( element =>{
    document.body.appendChild(element);
  })
})

webpack.common.js

module.exports = {
  entry: {
    main: './src/index.js'
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
    path: path.resolve(__dirname, '../dist')
  }
}

运行npm run dev-build打包。打开dist目录,发现第三方模块打包好的名字叫vendors~lodash.chunk.js,不再是之前的vendors~lodash.js。我们的入口文件对应的都是filename的输出。如果不是入口文件,是异步引入或者间接产生的js文件,他就会走chunkFilename这个输出的配置参数。

接下来进入主题,css代码的分割

index.html

<!DOCTYPE html>
<html >
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>html template</title>
  </head>
  <body>
    <div ></div>
  </body>
</html>

index.js

import './style.css';
console.log(' hello world ');

style.css

body{
  background: #abcdef;
}

运行npm run dev-build。发现打包生成的文件只有main.js 和 vendors~main.chunk.js。但是浏览器打开index.html。背景已经有了。这是怎么回事呢?webpack在做css的打包的时候,会直接打包到js里面

如果我希望在打包生成代码的时候,如果我引入了css文件,那么把css文件打包到dist目录下。而不是直接引入到js文件里面。那么就需要引入一个插件

https://webpack.js.org/plugins/mini-css-extract-plugin
npm install --save-dev mini-css-extract-plugin

这个插件可以对css进行代码分割。这个插件不适合开发环境,因为官网说了,这个插件现在还暂时不支持热更新。

安装好之后看怎么使用,首先要在webpack中引入这个插件。首先打开线上配置文件

webpack.prod.js

const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const prodConfig = {
  mode: 'production',
  devtool: 'cheap-module-source-map',
  module: {
    rules:[{
      test: /\.scss$/,
      use: [
        MiniCssExtractPlugin.loader,
        {
          loader: 'css-loader',
          options: {
            importLoaders: 2
          }
        },
        'sass-loader',
        'postcss-loader'
      ]
    },{
      test: /\.css$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        'postcss-loader'
      ]
    }]
  },
  plugins:[
    new MiniCssExtractPlugin({})
  ]
}
module.exports = merge(commonConfig, prodConfig);

然后对应到webpack.common.js里面删除css,scss相关到配置。运行npm run build。发现多出了两个文件main.css 和 main.css.map

css打包好后,是未压缩的,要将打包好的css进行压缩,安装,optimize-css-assets-webpack-plugin

npm install optimize-css-assets-webpack-plugin -D

在webpack.props.js引入并配置

const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
  module.exports = {
    optimization: {
      minimizer: [new OptimizeCSSAssetsPlugin({})],
    },
}

运行 npm run build。会发现css文件被自动的合并压缩。

还有更高级的用法, 假设有很多个css,要打包到一个css文件里面

https://webpack.js.org/plugins/mini-css-extract-plugin

也可以实现

optimization: {
  splitChunks: {
    cacheGroups: {
      styles: {
        name: 'styles',
        test: /\.css$/,
        chunks: 'all',
        enforce: true, // 忽略到前面到配置,不管是minSize,maxSize等等,只要是css,都打包到同一个文件中
      },
    },
  },
},