css 文件的代码分割

之前写的都是js 代码分割,下面来看看css 代码分割。

先看看webpack.config.js 如下

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');


module.exports = {
  mode: 'development',
  devtool: "cheap-module-source-map",
  devServer: {
    contentBase: './bundle',
    open: true
  },
  entry: {
    main: './src/index.js'
  },
  module: {
    rules: [{
      test: /\.(png|jpg|gif)$/,
      use: {
        loader: 'url-loader',
        options: {
          name: '[name].[ext]',
          outputPath: 'imgs/',
          limit: 20480
        }
      }
    }, {
      test: /\.scss$/,
      use: ['style-loader', {
              loader: 'css-loader',
              options: {
                importLoaders: 2,
                // modules: true
              }
            },
            'sass-loader',
            'postcss-loader']
    }, {
      test: /\.(eot|ttf|svg)$/,
      use: {
        loader: 'file-loader'
      }
    }, {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }]
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'bundle')
  },
  optimization: {
    splitChunks: {
      chunks: 'async'
    }
  },
  plugins: [new HtmlWebpackPlugin({
    template: 'src/index.html'
  }),new CleanWebpackPlugin()]
}

output 中配置了filename 与 path 。output 中还有一个常配置项 chunkFilename。如下。

  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
    path: path.resolve(__dirname, 'bundle')
  },

那么filename 与 chunkFilename 有什么区别呢。

我们先把项目的src/index.js 改成下面这样

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

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

然后,运行打包命令。发现现在我们的文件名是这样的。js 文件分别是main.js 与 vendors~lodash.chunk.js。

入口文件(entry 中配置的文件),它对应到的是output 中的filename,因此得到的是main.js

main.js 中会引入lodash,而lodash 又被单独打包生成了一个文件。打包生成的这个文件,在整个代码的运行中,main.js 先执行,然后异步加载lodash,因此这个js 并不是个入口的js,而是一个被main.js 异步加载的间接js 文件。

那么打包生成这种间接js 文件,就会在output 中走 chunkFilename。

下面正式来讲解,如何在webpack 中进行css 代码的分割。这个得借助webpack 官网提供的一个插件 MiniCssExtractPlugin

webpack 官网 documentation > plugins > MiniCssExtractPlugin

这个插件就可以实现在webpack 中,对引入的 css 文件进行代码分割

我们改一下src/index.js 中代码,如下

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

再新建一个文件src/style.css,如下。

body {
    background: pink;
}

再在webpack 中配置一下.css 文件的loader,如下。

{
      test: /\.css$/i,
      use: ['style-loader', {
        loader: 'css-loader',
        options: {
          importLoaders: 1,
          // modules: true
        }
      },
        'postcss-loader'],
}

然后,打包代码。运行页面,会发现,页面已经有背景色了。

我们来看看打包生成的文件,只有html 与 js 文件。而html 中是没有刚刚的样式的。也就是说,webpack 在打包的时候会把我们的css 文件代码打包进 js 文件中。(CSS in JS)

那么,我们希望在打包css 文件的时候,单独将其打包在打包目录下的css 文件中,而不是打包进js 文件中。这个时候,就要借助插件 MiniCssExtractPlugin 。

我们先按照官网介绍下载,使用命令

npm install --save-dev mini-css-extract-plugin

下载好后,我们去配置webpack, 进入webpack.config.js,先require 引入这个插件,然后在plugins 中添加这个插件,再在module 中添加配置(之前我们在解析css 时最后一步是style-loader,现在不可以使用它了,将它替换为这个插件提供的loader),如下。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');


module.exports = {
  mode: 'development',
  devtool: "cheap-module-source-map",
  devServer: {
    contentBase: './bundle',
    open: true
  },
  entry: {
    main: './src/index.js'
  },
  module: {
    rules: [{
      test: /\.(png|jpg|gif)$/,
      use: {
        loader: 'url-loader',
        options: {
          name: '[name].[ext]',
          outputPath: 'imgs/',
          limit: 20480
        }
      }
    }, {
      test: /\.css$/i,
      use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              // modules: true
            }
          },
          'postcss-loader'
      ],
    }, {
      test: /\.scss$/,
      use: ['style-loader', {
              loader: 'css-loader',
              options: {
                importLoaders: 2,
                // modules: true
              }
            },
            'sass-loader',
            'postcss-loader']
    }, {
      test: /\.(eot|ttf|svg)$/,
      use: {
        loader: 'file-loader'
      }
    }, {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }]
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
    path: path.resolve(__dirname, 'bundle')
  },
  optimization: {
    splitChunks: {
      chunks: 'async'
    }
  },
  plugins: [
      new HtmlWebpackPlugin({
        template: 'src/index.html'
      }),
      new CleanWebpackPlugin(),
      new MiniCssExtractPlugin({})
  ]
}

好,我们运行打包命令。可以发现,现在生成了单独的css 文件。如下。

我们还可以给这个 plugin 配置一些参数, filename,chunkFilename 。

  plugins: [
      new HtmlWebpackPlugin({
        template: 'src/index.html'
      }),
      new CleanWebpackPlugin(),
      new MiniCssExtractPlugin({
        filename: '[name].css',
        chunkFilename: '[name].chunk.css'
      })
  ]

运行打包命令,我们发现css文件的名字还是main.css 。这是因为这个css 文件是被html 直接引用的,这种情况在filename 与chunkFilename 中,它会走前者。而如果它是间接的被引用的话,它走的就是后者。

下面,我们新建一个css 文件 src/style1.css ,如下

body {
    font-size: 50px;
}

然后同样在index.js 中引入

import './style.css';
import './style1.css';

console.log('hello world')

打包,会发现,webpack 将他们打包放入了同一个css文件,如下。

刚刚我们看到了,生成的css 文件没有做压缩,如果我们想生成压缩的css 代码,那么我们还需要一个插件“optimize-css-assets-webpack-plugin” :

先下载这个插件:

npm install --save-dev optimize-css-assets-webpack-plugin

下好后,我们先引入它。然后在optimization中添加minimizer ,如下。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
  mode: 'development',
  devtool: "cheap-module-source-map",
  devServer: {
    contentBase: './bundle',
    open: true
  },
  entry: {
    main: './src/index.js'
  },
  module: {
    rules: [{
      test: /\.(png|jpg|gif)$/,
      use: {
        loader: 'url-loader',
        options: {
          name: '[name].[ext]',
          outputPath: 'imgs/',
          limit: 20480
        }
      }
    }, {
      test: /\.css$/i,
      use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              // modules: true
            }
          },
          'postcss-loader'
      ],
    }, {
      test: /\.scss$/,
      use: ['style-loader', {
              loader: 'css-loader',
              options: {
                importLoaders: 2,
                // modules: true
              }
            },
            'sass-loader',
            'postcss-loader']
    }, {
      test: /\.(eot|ttf|svg)$/,
      use: {
        loader: 'file-loader'
      }
    }, {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }]
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
    path: path.resolve(__dirname, 'bundle')
  },
  optimization: {
    splitChunks: {
      chunks: 'async'
    },
    minimizer: [new OptimizeCSSAssetsPlugin({})]
  },
  plugins: [
      new HtmlWebpackPlugin({
        template: 'src/index.html'
      }),
      new CleanWebpackPlugin(),
      new MiniCssExtractPlugin({
        filename: '[name].css',
        chunkFilename: '[name].chunk.css'
      })
  ]
}

Done.

以上是基本的配置,还有一些复杂配置主要针对多入口的打包,请参考官方文档 https://webpack.js.org/plugins/mini-css-extract-plugin/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值