从零配置webpack 5 + React脚手架(二)

1,855 阅读2分钟

加载 CSS

src/app.css

.box1 {
  background-color: #ccc;
}

src/app.js

import React, { Component } from 'react';
import './app.css';

class App extends Component {
  render() {
    return (
      <>
        <div className="box">
          <div className="box1">my-project!!!----1</div>
          <div className="box2">my-project!!!----</div>
        </div>
      </>
    );
  }
}

export default App;

执行 npm start 看看能否给我们第一个 div 加上颜色呐。不出意外的话你的页面应该是什么都没有展示。浏览器中的 console 也应该是报了错与此同时运行 npm start 的终端也报了 error。 image.png image.png 来吧,让我们处理报错。

安装依赖

npm install --save-dev style-loader css-loader

webpack.dev.config.js

const path = require('path');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.config.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = merge(common, {
  mode: 'development',
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000,
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader', // 将 JS 字符串生成为 style 节点
          'css-loader', // 将 CSS 转化成 CommonJS 模块
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      inject: 'body',
      hash: false,
    }),
  ],
});

以上配置完成后,通过 import "./app.css" 引入依赖的样式的文件。当该模块运行时,解析完的 css 代码用 <style>标签包裹后,将其注入到 html 文件的  中。

再执行 npm start 看看页面是不是好了

注意⚠️

在Webpack中,loader的执行顺序是从右向左执行的,webpack先将所有css模块依赖解析完得到计算结果再创建style标签。因此把style-loader放在css-loader的前面。

至于为什么是从右到左执行而不是从左到右?因为webpack选择了compose这样的函数式编程方式,而 gulp 却选择应用从左到右的pipe 管道式编程。

打包 CSS

style 样式是通过 style-loader 预处理,插入到了 head 标签内,但是我们平常写样式的时候,一定是通过引入外部 css 文件进行样式引入的,那我们怎么做呢?使用插件 mini-css-extract-plugin :

安装依赖

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

webpack.prod.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = merge(common, {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'style/[name].[hash:6].css',
    }),
  ],
});

npm run build 打包试试,dist 目录下是不是多了个 style 文件夹

压缩打包出的 CSS 文件

安装依赖

npm install css-minimizer-webpack-plugin --save-dev

webpack.prod.config.js

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = merge(common, {
  optimization: {
    minimize: true,
    minimizer: [new CssMinimizerPlugin()],
  },
 });

执行 npm run build 查看 dist 目录下打包出的 css 文件是不是代码被压缩了。

接着让 Less 或 Sass 起飞

安装依赖

npm install less less-loader --save-dev // less
npm install sass sass-loader node-sass --save-dev // sass

将之前的 app.css 修改成 app.less 或 app.scss,记得引入的路径也相应的修改。

src/app.less

.box {
  .box1 {
    background-color: #ccc;
  }
  .box2 {
    background-color: #ff0;
  }
}

Less 和 Sass 的开发配置

webpack.dev.config.js

module: {
  rules: [
    {
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader'],
    },
    {
      test: /\.s[ac]ss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
    },
  ];
}

执行 npm start 看看。

Less 和 Sass 的打包配置

webpack.prod.config.js

module: {
  rules: [
    {
      test: /\.less$/,
      use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
    },
    {
      test: /\.(sass|scss)$/,
      use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
    },
  ];
}

执行 npm run build 看看less文件或scss文件是否打包成成功。

压缩 JS 文件

安装 terser-webpack-plugin

npm install terser-webpack-plugin --save-dev

webpack.prod.config.js **

const TerserPlugin = require("terser-webpack-plugin");
  
optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true, // 屏蔽log
          },
        },
      }),
    ],
  },

执行 npm run build 查看 dist 目录下打包出的 js 文件是不是代码被压缩了。

打包编译时看看我们命令行的 js/index-bundle 是不是减少了几 kb,当然,随着业务代码越来越多,这部分差距会渐渐变大。

此时你的webpack.prod.config.js文件应该是这样的

const { merge } = require('webpack-merge');
const common = require('./webpack.common.config.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = merge(common, {
  mode: 'production',
  output: {
    filename: 'js/[name]-bundle-[hash:6].js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
      },
      {
        test: /\.(sass|scss)$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      filename: 'index.html',
      inject: 'body',
      minify: {
        removeComments: true,
      },
    }),
    new MiniCssExtractPlugin({
      filename: 'style/[name].[hash:6].css',
    }),
    new CleanWebpackPlugin(),
  ],

  optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin(),
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true, // 屏蔽log
          },
        },
      }),
    ],
  },
});

下一节,进行url-loader等相关配置