接上篇......

十三、集成CSS和SASS支持

1、建一个css文件
assets/app.css

html, body {
    padding: 0;
    margin: 0;
    background-color: #f5f5f5;
}

2、安装loader(先处理CSS文件)

cnpm i style-loader -D
cnpm i css-loader -D

3、配置module.rules
修改config.js

// 两个环境都需要的公共配置

// 从node进程中引入path模块
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { ProgressPlugin, ProvidePlugin } = require('webpack') // webpack自带插件

module.exports = {
    entry: {
        // 把第三方库打包到vendors.js中,从业务代码中抽离出来,为了以后部署时做CDN优化
        vendors: ['react', 'react-dom/client'],
        // 可以给入口文件取个名字,给output使用
        app: {
            // 用import引入main.js作为入口文件
            import: path.resolve(__dirname, '../', 'src/main.js'),
            dependOn: 'vendors' // 用dependOn指定业务代码app依赖于vendors,先打包vendors,再打包app
        }
    },

    // 出口
    output: {
        // 自定义打包结果的输出目录,默认是dist目录,这里只能使用绝对路径
        path: path.resolve(__dirname, '../', 'dist'),
        // 指定打包结果的JS名称规范
        // filename: 'bundle.js' // 量词,一捆、一束
        filename: 'js/[name].[chunkhash:8].js',
        // 每次build打包时,都自动先删除dist中的旧文件
        clean: true
    },

    // 插件
    // 所有webpack插件都是class,用的时候需要new
    plugins: [
        // 用于把JS脚本和index.html自动注入合并
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, '../', 'public/index.html'),
            inject: 'body', // 把JS注入到body结束标签前面
            filename: 'index.html', // 指定打包成功后这个模板叫什么名字
            title: '测试'
        }),
        // 添加编译进度条
        new ProgressPlugin({
            handler(percentage, message, ...args) {
                console.log(percentage, message, ...args)
            }
        }),
        // 从node_modules中加载react包,将其放在全局变量React中,这样之后所有的文件模块都可以直接访问
        new ProvidePlugin({
            React: 'react'
        }),
    ],

    // 在webpack眼中一切文件皆模块,webpack必须使用各种loaders来处理各种不同的模块文件
    module: {
        // 定义模块编译的规则和方式
        rules: [
            {
                test: /\.(js|jsx|ts|tsx)$/, // 检测模块以js结尾
                use: ['babel-loader'], // 使用babel编译器把ES6+的代码编译成ES5
                exclude: /node_modules/ // 排除node_modules目录下的第三方包文件
            },
            {
                test: /\.(css)$/,
                use: ['style-loader', 'css-loader'], // 多个loader从右向左执行
                exclude: /node_modules/
            }
        ]
    }
}

{
    test: /\.(css)$/,
    use: ['style-loader', 'css-loader'], // 从右向左执行
    exclude: /node_modules/
}

webpack工作时,遇到以.css结尾的模块时,先用css-loader加载并解析返回css代码,接着由style-loader把css代码插入到head标签中

4、把项目运行起来查看

5、打包把CSS抽离出来
把配置从config.js中移出来

修改serve.js

// 只有开发环境才需要用到配置
module.exports = {
    mode: 'development',
    devtool: 'inline-source-map',

    // 本地服务配置
    devServer: {
        port: 8000
    },

    module: {
        rules: [
            {
                test: /\.(css)$/,
                use: ['style-loader', 'css-loader'], // 从右向左执行
                exclude: /node_modules/
            }
        ]
    }
}

修改build.js

// 只有打包时才用到配置
module.exports = {
    mode: 'production',
    devtool: 'source-map',

    module: {
        rules: [
            {
                test: /\.(css)$/,
                use: ['style-loader', 'css-loader'], // 从右向左执行
                exclude: /node_modules/
            }
        ]
    }
}

安装插件:

cnpm i mini-css-extract-plugin -D

修改build.js

// 只有打包时才用到配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    mode: 'production',
    devtool: 'source-map',

    plugins: [new MiniCssExtractPlugin()],

    module: {
        rules: [
            {
                test: /\.css$/i,
                use: [MiniCssExtractPlugin.loader, "css-loader"],
                exclude: /node_modules/
            },
        ]
    }
}

这样子的话,起本地服务,css包含在app中。build打包,css会分离出来

6、为MiniCssExtractPlugin插件增加选项
修改build.js

// 只有打包时才用到配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    mode: 'production',
    devtool: 'source-map',

    plugins: [new MiniCssExtractPlugin({
        filename: 'css/[name].[contenthash:8].css',
    })],

    module: {
        rules: [
            {
                test: /\.css$/i,
                use: [MiniCssExtractPlugin.loader, "css-loader"],
                exclude: /node_modules/
            },
        ]
    }
}

css文件放入单独的目录,解决浏览器缓存刷新问题

7、集成SASS

cnpm i sass-loader sass -D

修改serve.js

// 只有开发环境才需要用到配置
module.exports = {
    mode: 'development',
    devtool: 'inline-source-map',

    // 本地服务配置
    devServer: {
        port: 8000
    },

    module: {
        rules: [
            {
                test: /\.(css|scss)$/i,
                use: ['style-loader', 'css-loader', 'sass-loader'], // 从右向左执行
                exclude: /node_modules/
            }
        ]
    }
}

修改build.js

// 只有打包时才用到配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    mode: 'production',
    devtool: 'source-map',

    plugins: [new MiniCssExtractPlugin({
        filename: 'css/[name].[contenthash:8].css',
    })],

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

修改app.css,改名app.scss

$c: blue;

html, body {
    padding: 0;
    margin: 0;
    background-color: #f5f5f5;
    color: $c;
}

遇到以.scss结尾的模块时,先使用sass-loader加载模块,并交给sass编译器进行编译,编译结果得到css模块,再使用css-loader

注意:当处理一种文件模块,需要多个loaders时,先工作的loader放在数组的后面

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐