Skip to content

样式处理2

刚才我们的样式只能插入到模板的style标签内,我们能不能把它抽离出来,抽离成link标签的形式?

都放在style标签的话,要是很多时可能会阻塞。

所以我们可以配置一个抽离css样式的插件。

mini-css-extract-plugin

这个插件是专门用来抽离css样式的,先来安装一下,以前webpack3用的是另一个插件,已经废弃了,webpack4用的就是这个插件

shell
# mini-css-extract-plugin -D
yarn add mini-css-extract-plugin@0.7.0 -D

修改配置文件webpack.config.js

js
// webpack-dev-1\webpack.config.js
// webpack是node写出来的,所以使用node的语法

let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
let MiniCssExtractPlugin = require('mini-css-extract-plugin') // 引入插件

module.exports = {
    devServer: { // 开发服务器的配置
        port: 3000, // 默认端口是8080,这里可以改
        progress: true, // 打包时候的进度条
        contentBase: './build', // 以哪个文件夹作为服务的根目录 
        open: true, // 服务启动完毕后,直接打开浏览器
        compress: true, // 启动gzip压缩
    },

    mode: 'development', // 模式,默认两种模式,production 和 development

    entry: './src/index.js', // 入口

    output: {
        // 带hash戳的文件,:8限制一下hash戳的长度
        filename: 'bundle.[hash:8].js', // 打包后的文件名
        path: path.resolve(__dirname, 'build'), // 打包后的路径,必须是一个绝对路径
    },


    plugins: [ // 是一个数组,放着所有的webpack插件
        // 插件是一个类,通过new的方式来引用
        new HtmlWebpackPlugin({
            template: './src/index.html', // 告诉插件,是以这个目录下的index.html为模板
            filename: 'index.html', // 告诉插件,打包后的文件叫什么名字,这里也叫index.html
            hash: true, // 引用的时候可以加一个hash戳
        }),
        // 插件的使用就没有先后顺序了,随便放就行
        // 引入抽离css样式的插件,
        new MiniCssExtractPlugin({
            filename: 'main.css', // 告诉插件,抽离出的样式文件的名字叫什么,这里叫main.css
        }),
    ],

    module: { // 模块
        rules: [ // 规则,在这里面配置各种loader
            // css-loader 解析css文件,@import语法的
            // style-loader 把解析后的css文件 插入到head标签中
            // loader有个特点,希望单一,一个loader干一件事
            /* 
                loader的用法
                1. 只用字符串,就是只用一个loader
                2. 多个loader,需要一个数组 [],数组里可以放字符串,或者对象,对象的话就可以配置loader的参数了
            */
            // loader的顺序,默认是从右向左执行,从下往上执行
            {
                test: /\.css$/,
                use: [
                    // 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    // 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
                    MiniCssExtractPlugin.loader, // 若果想抽离多个文件,可以在new一个出来,一个抽离css一个抽离less都行
                    // 这里就用一个了
                    'css-loader', // 解析 @import语法 解析 css
                    'less-loader' // 把less 转换为 css
                ]
            },
        ],
    }
}

然后我们再打包一下,npm run build,发现已经把css文件和less都抽离到了main.css上

css
/* webpack-dev-1\build\main.css */

/* webpack-dev-1\src\a.css */
body {
    background-color: blue;
}
/* webpack-dev-1\src\index.css */

body {
    background-color: red;
}
/* webpack-dev-1\src\index.less */
body div {
  border: 1px solid orange;
}

给样式添加浏览器前缀 autoprefixer、postcss-loader

我们修改一下index.css中的样式,因为有的样式对不同的浏览器兼容不同,所以需要手动的增加浏览器前缀

css
/* webpack-dev-1\src\index.css */
@import './a.css';

body {
    background-color: red;
    transform: rotate(45deg);
}

其实webpack有插件也帮我们做好这件事了

安装autoprefixer、postcss-loader

shell
# autoprefixer、postcss-loader -D
yarn add autoprefixer@9.5.1 postcss-loader@3.0.0 -D

修改配置文件webpack.config.js

js
module: { // 模块
        rules: [ // 规则,在这里面配置各种loader
            // css-loader 解析css文件,@import语法的
            // style-loader 把解析后的css文件 插入到head标签中
            // loader有个特点,希望单一,一个loader干一件事
            /* 
                loader的用法
                1. 只用字符串,就是只用一个loader
                2. 多个loader,需要一个数组 [],数组里可以放字符串,或者对象,对象的话就可以配置loader的参数了
            */
            // loader的顺序,默认是从右向左执行,从下往上执行
            {
                test: /\.css$/,
                use: [
                    // 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    // 应该在解析css之前增加前缀
                    'postcss-loader',
                ]
            },
            {
                test: /\.less$/,
                use: [
                    // 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
                    MiniCssExtractPlugin.loader, // 若果想抽离多个文件,可以在new一个出来,一个抽离css一个抽离less都行
                    // 这里就用一个了
                    'css-loader', // 解析 @import语法 解析 css
                    // 应该在解析css之前增加前缀
                    'postcss-loader',
                    'less-loader' // 把less 转换为 css
                ]
            },
        ],
    }

注意postcss-loader应该先调用,然后再处理css,有顺序的,放反了会报错

如果我们光加loader,不使用插件,会提示我们没有找到PostCss Config

image-20220107171337717

所以我们在根目录下新建一个postcss.config.js文件,默认调用这个loader时,会调用这个配置文件

js
// webpack-dev-1\postcss.config.js

// 需要到处一个模块
// 模块里放一些插件,告诉人家用哪个插件
module.exports = {
    Plugins: [
        require('autoprefixer')
    ]
}

再来打包一下,npm run build

我的没有生效,先放一放...查看了很多解决办法,但是并没有卵用,以后再研究

image-20220107183700371

有个这样的提示,说不定是用法改了,得另外配置一些前缀。以后有时间再研究。

压缩抽离出来的css

刚才使用mini-css-extract-plugin插件已经把样式文件抽离出来了,但是并没有压缩,我们想把样式文件也压缩的话,需要一些配置项

需要修改webpack.config.js文件,增加优化项配置minimize,优化体积,默认情况下会调用UglifyJsPlugin压缩js,

需要安装另外一个插件optimize-css-assets-webpack-plugin,压缩css文件

我们安装一下

shell
# optimize-css-assets-webpack-plugin -D
yarn add optimize-css-assets-webpack-plugin@^5.0.1 -D

上面的是生产模式用来压缩css文件的,但是如果使用它的话,就必须配置优化项,配置优化项时候,还得硬性开始js压缩,依赖另外一个插件uglifyjs-webpack-plugin,我们也来安装一下

shell
# uglifyjs-webpack-plugin -D
yarn add uglifyjs-webpack-plugin@^1.1.1 -D

修改webpack.config.js文件

js
// webpack-dev-1\webpack.config.js
// webpack是node写出来的,所以使用node的语法

let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
let MiniCssExtractPlugin = require('mini-css-extract-plugin') // 引入插件

let OptimizeCss = require('optimize-css-assets-webpack-plugin') // 引入插件 压缩css的
let UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 压缩js文件的插件

module.exports = {
    // 配置优化项
    optimization: {
        minimizer: [ // 是一个数组,还得优化js
            new UglifyJsPlugin({
                cache: true, // 是否用缓存
                parallel: true, // 是否并发压缩
                sourceMap: true,// 线上用来调试的映射文件,ES6转ES5时,代码不好调试,会有一个映射文件
            }),
            new OptimizeCss(), // 开启优化css后,生产模式css文件也会被压缩,但是必须配置js压缩,如果不配置,js生产模式就不会被压缩了
        ]
    },

    devServer: { // 开发服务器的配置
        port: 3000, // 默认端口是8080,这里可以改
        progress: true, // 打包时候的进度条
        contentBase: './build', // 以哪个文件夹作为服务的根目录 
        open: true, // 服务启动完毕后,直接打开浏览器
        compress: true, // 启动gzip压缩

    },

    mode: 'production', // 模式,默认两种模式 production 和 development

    entry: './src/index.js', // 入口

    output: {
        // 带hash戳的文件,:8限制一下hash戳的长度
        filename: 'bundle.[hash:8].js', // 打包后的文件名
        path: path.resolve(__dirname, 'build'), // 打包后的路径,必须是一个绝对路径
    },


    plugins: [ // 是一个数组,放着所有的webpack插件
        // 插件是一个类,通过new的方式来引用
        new HtmlWebpackPlugin({
            template: './src/index.html', // 告诉插件,是以这个目录下的index.html为模板
            filename: 'index.html', // 告诉插件,打包后的文件叫什么名字,这里也叫index.html
            hash: true, // 引用的时候可以加一个hash戳
        }),
        // 插件的使用就没有先后顺序了,随便放就行
        // 引入抽离css样式的插件,
        new MiniCssExtractPlugin({
            filename: 'main.css', // 告诉插件,抽离出的样式文件的名字叫什么,这里叫main.css
        }),
    ],

    module: { // 模块
        rules: [ // 规则,在这里面配置各种loader
            // css-loader 解析css文件,@import语法的
            // style-loader 把解析后的css文件 插入到head标签中
            // loader有个特点,希望单一,一个loader干一件事
            /* 
                loader的用法
                1. 只用字符串,就是只用一个loader
                2. 多个loader,需要一个数组 [],数组里可以放字符串,或者对象,对象的话就可以配置loader的参数了
            */
            // loader的顺序,默认是从右向左执行,从下往上执行
            {
                test: /\.css$/,
                use: [
                    // 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    // 应该在解析css之前增加前缀
                    'postcss-loader',
                ]
            },
            {
                test: /\.less$/,
                use: [
                    // 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
                    MiniCssExtractPlugin.loader, // 若果想抽离多个文件,可以在new一个出来,一个抽离css一个抽离less都行
                    // 这里就用一个了
                    'css-loader', // 解析 @import语法 解析 css
                    // 应该在解析css之前增加前缀
                    'postcss-loader',
                    'less-loader' // 把less 转换为 css
                ]
            },
        ],
    }
}

这样的话就发现生产模式下,js和css文件都已经压缩好了。

总结

使用mini-css-extract-plugin可以将css文件抽离成单独的文件。

使用autoprefixer、postcss-loader可以在css的样式加一些浏览器前缀。

使用optimize-css-assets-webpack-plugin可以压缩抽离出的css文件,但是得配置优化项,优化项还需把js的压缩方式配置一下,需要使用uglifyjs-webpack-plugin插件。

参考

https://www.bilibili.com/video/BV1a4411e7Bz?p=6&spm_id_from=pageDriver