Webpack 4 + React Part 3

Views: 1018
Wrote on May 13, 2020, 8:31 p.m.

前言:

这一节我们将在脚手架中引入CSS,SASS,LESS,并且实现代码压缩,以及PostCSS的使用。

先让CSS跑起来

新建CSS文件

在我们的 /src 目录下,新建一个文件名为 app.css ,并输入以下代码:

.App {
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: lightcoral;
}

h1 {
  font-size: 16px;
  color: #fff;
}

在app.js中引入css

打开 /src/app.js ,添加以下代码:

import './app.css';

配置loader

wbpack只能编译js文件,css文件是无法被识别并编译的,我们需要loader加载器来进行预处理。 首先安装 style-loadercss-loader

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

注:

  • 遇到后缀为.css的文件,webpack先用css-loader加载器去解析这个文件,遇到“@import”等语句就将相应样式文件引入(所以如果没有css-loader,就没法解析这类语句),最后计算完的css,将会使用style-loader生成一个内容为最终解析完的css代码的style标签,放到head标签里。
  • loader是有顺序的,webpack肯定是先将所有css模块依赖解析完得到计算结果再创建style标签。因此应该把style-loader放在css-loader的前面(webpack loader的执行顺序是从右到左)。

配置module.export.rules

在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 UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = merge(common, {
  //...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [ 
          'style-loader', 
          'css-loader' 
        ]
      }
    ]
  },
  //...
});

现在,执行一下 npm run build ,打开页面,发现样式生效。你再打开控制台看Elements,发现style样式已经插入到了****内。

打包出CSS独立文件

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

安装 mini-css-extract-plugin

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

引入 mini-css-extract-plugin

webpack.prod.config.js 中引入:

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

配置plugin

module.exports = merge(common, {
  plugins: [
    //...
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash].css',
      chunkFilename: 'css/[id].[hash].css',
    }),
  ]
});

修改loader

module: {
    rules: [
      {
        test: /\.css$/,
        use: [ 
          MiniCssExtractPlugin.loader,
          'css-loader' 
        ]
      }
    ]
  },

现在你的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 UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = merge(common, {
  mode: 'production',
  output: {
    filename: 'js/[name].[chunkhash:8].bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [ 
          MiniCssExtractPlugin.loader,
          'css-loader' 
        ]
      }
    ]
  },
  optimization: {
    minimizer: [new UglifyJsPlugin()],
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      cacheGroups: {
        framework: {
          priority: 100,
          test: "framework",
          name: "framework",
          enforce: true
        },
        vendors: {
          priority: -10,
          test: /node_modules/,
          name: "vendor",
          enforce: true,
        },
      }
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'public/index.html',
      inject: 'body',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
      },
    }),
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash].css',
      chunkFilename: 'css/[id].[hash].css',
    }),
  ]
});

我们再执行一下 npm run build ,查看dist目录,你会发现css文件已经被单独打包出来了。

压缩打包出的CSS文件

我们打开dist目录下打包生成的css文件,你会发现他和我们写的是一模一样的,这意味着该代码没有被压缩,使用插件optimize-css-assets-webpack-plugin来做这项工作。

安装optimize-css-assets-webpack-plugin

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

引入optimize-css-assets-webpack-plugin

webpack.prod.config.js 中引入:

const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

配置minimizer参数

optimization: {
  minimizer: [
    new UglifyJsPlugin(),
    new OptimizeCssAssetsPlugin({
      assetNameRegExp:/\.css$/g,
      cssProcessor:require("cssnano"),
      cssProcessorPluginOptions:{
        preset:['default', { discardComments: { removeAll:true } }]
      },
      canPrint:true
    })
  ],
  //...
}
参数 意义
assetNameRegExp 正则表达式,用于匹配需要优化或者压缩的资源名。默认值是
/.css$/g
cssProcessor 用于压缩和优化CSS 的处理器,默认是 cssnano.
cssProcessorPluginOptions 传递给cssProcessor的插件选项,默认为{}
canPrint 表示插件能够在console中打印信息,默认值是true
discardComments 去除注释

另外,这段配置也是可以放到 plugins 这个属性下进行配置的。 配置完成,执行 npm run build ,查看dist目录下打包出的css文件是不是代码被压缩了!

接着让Less或Sass飞起来

我们写项目的时候没几个人会去写css吧?sass或less对于工作效率的提高是肉眼可见的,但是我们webpack也同样无法理解这种编写方式,那就需要配置loader做预处理,将其转换为css。

安装less-loader,sass-loader

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

配置loader

webpack.prod.config.js 中的 module.rules 内增加两个对象:

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

我们将 src 目录下的 app.css 改为 app.lessapp.sass ,在里面改为以下代码:

.App {
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: lightcoral;
  h1 {
    font-size: 16px;
    color: #fff;
  }
}

然后修改 app.js 中的引入 import 'app.less'import 'app.sass'

执行 npm run build 看看是否把less文件或sass文件打包成了dist目录下的css文件

使用PostCSS

postcss 一种对css编译的工具,类似babel对js的处理,常见的功能如: 1 . 使用下一代css语法 2 . 自动补全浏览器前缀 3 . 自动把px代为转换成rem 4 . css 代码压缩等等 postcss 只是一个工具,本身不会对css一顿操作,它通过插件实现功能,autoprefixer 就是其一。

安装postcss

npm install postcss postcss-loader --save-dev

安装postcss某个插件,以Autoprefixer举例

npm install autoprefixer --save-dev

配置postcss.config.js

根目录新建postcss.config.js

module.exports = {
  plugins: [
    require('autoprefixer')({ browsers: ['last 5 version', '>1%', 'ie >=8'] })
  ]
};

设置loader

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

执行 npm run build 可以,浏览器打开dist目录下的index.html,控制台看css样式,加上了浏览器前缀: image.png

我们可以复制一份webpack.prod.config.js中关于rules的配置到webpck.dev.config.js,修改第一个为style-loader,因为我们在开发环境下没必要打包单独文件。

以下是webpck.dev.config.js部分配置

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

现在执行 npm run start 来启动开发环境。

到此为止,我们已经基本搭起了一个简单的react脚手架,下一节,我们还需要再进行相关配置的优化!很重要!

>> 本博客分享自vortesnail/blog,供自学使用,非商用 <<