webpack4打包踩坑——分离css文件

2,666 阅读1分钟

今天尝试用ExtractTextPlugin插件进行css文件的分离,项目如下:

project

./split-css/
├── README.md
├── dist
│   ├── app.bundle.js
│   ├── app.bundle.js.map
│   └── index.html
├── package-lock.json
├── package.json
├── src
│   ├── index.js
│   └── style.css
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js

webpack.common.js

  const path = require('path');
  const HtmlWebpackPlugin = require('html-webpack-plugin');
  const { CleanWebpackPlugin } = require('clean-webpack-plugin');
+ const ExtractTextPlugin = require('extract-text-webpack-plugin')

  module.exports = {
      entry: {
          app: "./src/index.js"
      },
      output: {
          filename: '[name].bundle.js',
          path: path.resolve(__dirname, 'dist')
      },
+     module: {
+         rules: [
+             {
+                 test: /\.css$/,
+                 use: ExtractTextPlugin.extract({
+                     fallback: "style-loader",
+                     use: ['css-loader']
+                 })
+                 // use: [
+                 //     'style-loader',
+                 //     'css-loader'
+                 // ]
+             }
+         ]
+     },
      plugins: [
          new CleanWebpackPlugin(),
          new HtmlWebpackPlugin({
              title: 'Production'
          }),
+         new ExtractTextPlugin({
+             // disable: process.env.NODE_ENV === 'production'?false:true,
+             filename: 'main.css'
+         })
      ]
  }

package.json

{
  "name": "split-css",
  "sideEffects": false,
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.prod.js",
    "start": "webpack-dev-server --open --config webpack.dev.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.4.2",
    "extract-text-webpack-plugin": "^3.0.2",
    "html-webpack-plugin": "^3.2.0",
    "style-loader": "^1.1.3",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.10.3",
    "webpack-merge": "^4.2.2"
  },
  "dependencies": {
    "loadsh": "0.0.4"
  }
}

然而,在运行npm run build时,却报了如下的错误❌

node:94261) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
(node:94261) UnhandledPromiseRejectionWarning: Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead

小插曲:在将插件的配置代码注销,又重新变异了一次,页面却没有样式。后面排查出来是在package.json文件中配置了"sideEffects": false,将所有文件标识为没有副作用,导致在生产模式默认tree-shaking的过程中,css代码被当做无效代码清除掉了。改成"sideEffects": [ "*.css" ],即可。

经过查阅资料,发现extract-text-webpack-plugin目前版本已经被废弃,官方建议使用mini-css-extract-plugin

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 = {
    entry: {
        app: "./src/index.js"
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader
                    },
                    'css-loader',
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'Production'
        }),
        new MiniCssExtractPlugin({
            filename: 'main.css'
        })
    ]
}