重构之路:配置css/less,img等loader和dev-server

本文详细介绍了如何使用Webpack进行前端项目的高效配置,包括devServer的设置、css和less的加载器配置、图片资源处理及模块热更新的实现,助力开发者提升开发效率。

开始

这章我们先把一些css和img给配置了,还有热加载的一些插件。

首先我们先配置控制台的命令,我们每次打包的时候都需要执行webpack这条命令,然后在打包后的文件夹里打开index.html进行预览,我们能不能直接在修改的时候直接在网页上预览呢?当然可以,下面开始配置。

配置devServer

先在控制台执行:

yarn add webpack-dev-server -D

然后去webpack.config.js里配置,注意这里的devServer和module是同级的:

devServer: {
        port:8080,//端口号
        open:true,//自动打开浏览器
        compress: true,//开启gzip压缩
        overlay:true,//控制台错误显示在浏览器上
        contentBase: path.join(__dirname, "dist"),//指定资源目录
    },

然后去package.json里配置,这里的scripts和的devDependencies是同级的:

"scripts": {
    "dev":"webpack-dev-server",
    "build":"webpack"
  },

这样配置完后我们就可以去控制台执行:

yarn run dev

发现浏览器自动弹出窗口,并且浏览器控制台有输出内容了,我们在index.js写一个alert(1);并保存。发现浏览器自动刷新,并弹出1.这样我们就成功配置了devServer。
在这里插入图片描述

配置css

我们去src下新建一个index.css,写个background:lightblue,在index.js的顶部引入这个css,

import "./index.css"

然后去控制台执行发现控制台报错:
在这里插入图片描述
提示我们需要一个合适的loader来处理css文件。

去控制台执行:

yarn add css-loader style-loader -D

然后在webpack.config.js里配置:

{
                test:/\.css$/,
                use:[
                    "style-loader",
                    "css-loader"
                ]
            }

再去控制台执行yarn run dev,发现浏览器背景颜色已经变成蓝色了,那就成功了。
但是还有,我们在写css3的时候,有时候需要写很多的前缀兼容语法,写多了就烦了啊,这时候我们就需要用到postcss-loader,这个插件可以帮助我们自动加上css的兼容语法。

我们先去index.css里写上:

html,body{
    height:100%;
    background:linear-gradient(lightsalmon,lightblue,lightcoral);
}

在控制台执行:

yarn add postcss-loader autoprefixer -D

在去webqpck.config.js里配置:

	{
                test:/\.css$/,
                use:[
                    "style-loader",
                    "css-loader",
                    {
                        loader:'postcss-loader',
                        options:{
                            plugins:[
                                require('autoprefixer')({
                                    browsers:['last 5 versions','>0.01%']
                                })
                            ]
                        }
                    }
                ]
            }

然后打开浏览器,我们可以发现,样式的地方变成了这样,已经帮我们加上了前缀(爽):
在这里插入图片描述

配置less

配置less的方法和css差不多,先在控制台执行:

yarn add less less-loader -D

再去webpack.config.js里把css的配置复制一份,修改成下面这样:

{
                test:/\.less$/,
                use:[
                    "style-loader",
                    "css-loader",
                    {
                        loader:'postcss-loader',
                        options:{
                            plugins:[
                                require('autoprefixer')({
                                    browsers:['last 5 versions','>0.01%']
                                })
                            ]
                        }
                    },
                    "less-loader"
                ]
            },

去src下新建一个index.less文件,在index.js里引入,再写一点less的语法

html,body{
  background:lightblue;
  #root{
    width: 100px;
    height:100px;
    background: #000;
  }
}

在浏览器里进行预览,变成下面这样就成功了。
在这里插入图片描述

配置img

再来配置img,我们去index.css里将背景修改成图片:

background:url("./地球.jpg") no-repeat;

打开控制台执行,又发现报错,需要一个合适的loader来处理,执行:

yarn add url-loader file-loader -D

在webapck.config.js里配置:

{
                test:/\.(jpg|jpeg|png|gif|svg)$/,
                use:{
                    loader:'url-loader',
                    options:{
                        limit:3*1024,//小于3kb使用base64编码
                        outputPath:'img/',
                    }
                }
            }

这里我多配置了一个limit和ouputPath,limit是当图片小于自定义的值时,会转化成base64编码,这样可以减少http的请求来达到优化的目的,ouputPath是将打包后的图片放到img文件夹里。

再打开浏览器,发现图片已经变成背景了。
在这里插入图片描述

配置模块热更新

我们前面已经发现,当我们修改了js或者css的内容的时候,浏览器已经可以自动刷新了,那什么是模块热更新呢,就是js或css更改的时候,浏览器不会自动刷新,只会在修改的地方进行更新,这样可以大大提升我们的开发效率。

我们去webpack.config.js里配置:

//在顶部写上
const webpack = require('webpack');
//在plugins里写上
new webpack.HotModuleReplacementPlugin()
//在devServer里加一个
hot:true//加上这个配置

再去index.js里写上:

if (module.hot) {
    module.hot.accept()
}

这个时候再打开浏览器,我们可以在js或者css里修改任何东西,保存之后查看浏览器,浏览器不会自动刷新就执行代码了。、

这个时候有的人会发现自己保存之后,浏览器很慢才响应,我们可以去webpack.config.js里写:

mode:'development'

这一行加在entry这个配置的上面,和entry是同级的存在。这个配置代表当前使用的是什么模式,我们暂时先设置为开发模式,后面我们会再修改的。

结尾

现在一些比较杂的配置已经差不多了,我们下面的一些章节的配置就比较关键了。

<think>我们想要在Webpack配置中处理.module.scss文件,并启用CSS Modules功能,同时使用`modules: { auto: true }`来自动为.module.scss文件启用CSS Modules,而普通.scss文件则不启用。 根据引用[1]引用[2]中的内容,我们知道在Webpack中,模块的处理是通过在`module.rules`中配置loader来实现的。同时,引用[5]提到,不能同时使用MiniCssExtractPluginstyle-loader来处理同一种样式文件,否则会导致问题。 当前配置中已经存在对.css.less的处理规则,我们需要添加对.scss文件的处理规则,并且要区分.module.scss普通.scss。 由于我们使用了`oneOf`规则(一组规则,当匹配到某个规则后就不再尝试后面的规则),因此我们需要在`oneOf`数组中添加两个规则: 1. 对于`.module.scss`文件,我们使用CSS Modules(设置`modules: { auto: true }`实际上可以简化为`modules: true`,但为了自动启用,我们可以使用`auto`选项,但注意css-loader的版本要求,在css-loader v4及以上支持`auto`选项) 2. 对于普通的`.scss`文件,我们不启用CSS Modules。 但是,注意我们已经在配置中有一个处理`sass/scss`的规则(非模块化的): { test: /\.s[ca]ss$/, use: [ 'style-loader', 'css-loader', 'sass-loader', ] } 我们需要修改这个规则,使其只匹配非模块化的scss文件,并添加一个新的规则来匹配模块化的scss文件(即.module.scss)。 由于`oneOf`规则是顺序匹配的,因此我们应该将更具体的规则(即.module.scss)放在前面,然后再匹配普通的scss文件。 步骤: 1. 在`oneOf`数组中,在现有的`.scss`规则之前,添加一个新的规则,用于处理`.module.scss`文件。 2. 新的规则中,使用`css-loader`的`modules`选项来启用CSS Modules,并设置`auto: true`(或者直接设置`modules: true`,但`auto`可以确保只有带.module.scss后缀的文件才启用,其他不启用,但这里我们通过test已经明确指定了.module.scss,所以设置`modules: true`即可)。 3. 注意,我们还需要保持与生产环境一致的样式提取方式(生产环境使用MiniCssExtractPlugin.loader,开发环境使用style-loader)。 但是,注意现有的scss规则(非模块化)没有区分开发生产环境,直接使用了style-loader。为了保持一致,我们应该让模块化的scss规则也使用同样的方式:在生产环境使用MiniCssExtractPlugin.loader,开发环境使用style-loader。 因此,我们修改如下: 首先,将现有的scss规则(非模块化)的test修改为:`/\.s[ca]ss$/`,但是要排除`.module.scss`文件,我们可以使用`exclude: /\.module\.scss$/`。或者,我们通过两个规则分别匹配,第一个规则匹配`.module.scss`,第二个规则匹配其他scss文件(不包含.module.scss)。 由于`oneOf`是顺序匹配,所以我们可以这样: 规则1:test: /\.module\.scss$/ 规则2:test: /\.s[ca]ss$/ 这样,.module.scss文件会被第一个规则匹配,其他的scss文件被第二个规则匹配。 然后,我们为规则1(模块化scss配置loader,包括: - 开发环境:style-loader,生产环境:MiniCssExtractPlugin.loader - css-loader(带modules选项) - postcss-loader(可选,根据项目需要,这里为了与cssless保持一致,我们加上) - sass-loader 规则2(普通scss)则保持原来的loader,但是需要调整一下,使其也支持生产环境开发环境使用不同的loader(与cssless规则一致)。 修改后的配置如下: 注意:原配置中已经有一个处理scss的规则(规则中只有style-loader, css-loader, sass-loader),我们将其修改为规则2(普通scss),并添加规则1(模块化scss)。 同时,为了与cssless规则保持一致,我们在scss规则中也加入postcss-loader(在css-loader之后,sass-loader之前?注意:sass-loader是负责编译scsscss,所以应该放在最后,即loader执行顺序是从后往前:sass-loader -> postcss-loader -> css-loader -> style-loader/MiniCssExtractPlugin.loader) 但是,注意:postcss-loader通常用于处理css,比如添加浏览器前缀,它应该在css-loader之前处理(因为css-loader可能会处理@import等)。所以顺序应该是:sass-loader -> postcss-loader -> css-loader -> style-loader/MiniCssExtractPlugin.loader 然而,原配置cssless规则中,postcss-loader是在css-loader之后,但这是错误的。正确的顺序应该是:先编译sass,然后使用postcss处理,然后使用css-loader处理,最后使用style-loader或MiniCssExtractPlugin.loader。 所以,我们需要调整顺序。同时,原配置中的cssless规则中,postcss-loadercss-loader后面,这可能是错误的,应该调整。 但是,为了不扩大问题,我们暂时只调整scss规则,并保持cssless规则不变(因为可能之前就是那样工作的,而且postcss-loader的文档建议放在css-loader之前,但也可以放在之后,具体看做什么处理)。实际上,最佳实践是:在css-loader之前使用postcss-loader,因为postcss-loader的作用是转换CSS,而css-loader是解析CSS中的@importurl()等。 因此,我们重新调整一下所有样式规则中loader的顺序: 对于所有样式规则,loader顺序应该为(从后往前): - 最后:style-loader 或 MiniCssExtractPlugin.loader - 然后:css-loader - 然后:postcss-loader(如果有) - 然后:预处理器(less-loader、sass-loader等) 但是,注意:在Webpack中,loader是从右到左(或从下到上)执行的。所以配置数组中的顺序应该是: [ style-loader, css-loader, postcss-loader, less-loader ] 这样执行顺序是:less-loader -> postcss-loader -> css-loader -> style-loader。 所以,我们修改现有的csslessscss规则,将postcss-loader放在css-loader之前(即数组中的位置在css-loader后面,因为从右到左执行,所以postcss-loader会在css-loader之前执行?不对,应该是:数组中的顺序是倒序执行,所以应该是: use: [ 'style-loader', // 第三个执行:将CSS注入到DOM 'css-loader', // 第二个执行:将CSS转成CommonJS模块 'postcss-loader', // 第一个执行:处理CSS,如加前缀 ] 这样显然不对,因为postcss-loader应该在css-loader之前处理?不对,css-loader的作用是处理CSS中的@importurl(),将CSS文件变成JS模块。postcss-loader是用来处理CSS的,它应该处理的是原始的CSS,所以应该在css-loader之前?但是,如果css-loader已经将@import等处理了,那么postcss-loader就无法处理那些导入的CSS了。所以,通常将postcss-loader放在css-loader之后,但在style-loader之前?这样也不行。 实际上,正确的顺序是: - 先由预处理器(如sass-loader)将scss转成css - 然后由postcss-loader处理(如加前缀) - 然后由css-loader处理,将CSS转为CommonJS模块 - 最后由style-loader或MiniCssExtractPlugin.loader处理 所以,在use数组中,应该是: [ isProduction ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader', 'postcss-loader', 'sass-loader' ] 但是,这样写的话,执行顺序是:sass-loader -> postcss-loader -> css-loader -> style-loader。这是正确的。 然而,我们之前配置css规则中,顺序是: [ isProduction ? ... : 'style-loader', 'css-loader', 'postcss-loader' ] 这个顺序是正确的,因为对于css文件,不需要预处理器,所以直接是:postcss-loader处理,然后css-loader,然后style-loader。 所以,我们保持cssless规则不变(less规则中,less-loader在最后,然后postcss-loader,然后css-loader,然后style-loader),这样执行顺序是:less-loader -> postcss-loader -> css-loader -> style-loader。 对于scss规则,我们也采用同样的顺序。 修改后的规则: 1. 模块化scss规则(.module.scss): { test: /\.module\.scss$/, use: [ isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', options: { modules: true, // 启用CSS Modules sourceMap: !isProduction, esModule: false } }, { loader: 'postcss-loader', options: { sourceMap: !isProduction } }, 'sass-loader' ] } 2. 普通scss规则(非模块化): { test: /\.s[ca]ss$/, exclude: /\.module\.scss$/, // 排除模块化的scss文件 use: [ isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', options: { sourceMap: !isProduction, esModule: false } }, { loader: 'postcss-loader', options: { sourceMap: !isProduction } }, 'sass-loader' ] } 然后,将这两个规则按顺序(模块化规则在前,普通规则在后)添加到`oneOf`数组中。 注意:原配置中已经有一个处理scss的规则(在oneOf数组中),我们需要将其替换为这两个规则。 另外,由于我们添加了postcss-loader到scss规则中,需要确保已经安装了postcss-loader相应的配置(比如postcss.config.js)。如果没有安装,需要安装。 同时,注意原配置中已经对cssless使用了postcss-loader,所以应该已经安装配置了。 最后,我们还需要注意,现有的处理scss的规则(即要被替换掉的那个)在oneOf数组中的位置。我们需要在它之前插入模块化scss规则,然后修改它(变成普通scss规则)或者删除它,然后插入新的普通scss规则。 由于原配置中已经有一个处理scss的规则(如下): { test: /\.s[ca]ss$/, use: [ 'style-loader', 'css-loader', 'sass-loader', ] } 我们将其替换为上述两个规则(模块化scss规则普通scss规则),并调整顺序,确保模块化规则在普通规则之前。 因此,修改后的`oneOf`数组将包含: ... 其他规则(如css, less), // 模块化scss { test: /\.module\.scss$/, use: [ ... ] }, // 普通scss { test: /\.s[ca]ss$/, exclude: /\.module\.scss$/, use: [ ... ] }, ... 其他规则 注意:原配置中已经有一个处理scss的规则,我们需要找到它并替换。 由于原配置中的scss规则在oneOf数组中,我们可以在原规则的位置替换为两条新规则。 但是,由于我们无法直接修改原规则(因为它是数组中的一个元素),我们可以通过重构oneOf数组来实现。 由于配置代码较长,我们只展示修改部分: 在`oneOf`数组中,找到原来的scss规则(test: /\.s[ca]ss$/),将其替换为两个新的规则(模块化scss规则普通scss规则)。 修改后的配置如下(只展示修改后的rules部分):</think>要在 Webpack 配置中添加对 `.module.scss` 文件的 CSS Modules 支持并使用 `modules: { auto: true }`,请按照以下步骤操作: ### 配置步骤 1. **修改 SCSS 规则** 在 `module.rules.oneOf` 数组中更新 SCSS 规则,添加 CSS Modules 支持: ```javascript{3-4,7-8,14-15,20-22,30-50} module.exports = { module: { rules: [ { oneOf: [ // ... 其他规则保持不变 ... // 新增:处理 .module.scss 文件(启用 CSS Modules) { test: /\.module\.scss$/, // 匹配 .module.scss 文件 use: [ isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', options: { modules: { auto: true, // 启用自动模块化 localIdentName: isProduction ? '[hash:base64]' : '[path][name]__[local]' // 开发环境显示可读类名 }, sourceMap: !isProduction } }, { loader: 'postcss-loader', options: { sourceMap: !isProduction } }, 'sass-loader' ] }, // 修改:处理普通 .scss 文件(不启用 CSS Modules) { test: /\.s[ca]ss$/, exclude: /\.module\.scss$/, // 排除模块化文件 use: [ isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', options: { sourceMap: !isProduction, esModule: false } }, { loader: 'postcss-loader', options: { sourceMap: !isProduction } }, 'sass-loader' ] }, // ... 其他规则保持不变 ... ] }, // ... Vue 加载器 ... ] } } ``` 2. **关键配置说明** - `modules.auto: true`:自动为文件名包含 `.module.` 的 SCSS 文件启用 CSS Modules - `localIdentName`:控制生成的类名格式(开发环境保留路径信息便于调试) - `exclude: /\.module\.scss$/`:确保普通 SCSS 文件不被模块化处理 3. **在组件中使用** ```vue <template> <div :class="$style.container"> <!-- 使用 $style 访问模块化类名 --> 模块化样式示例 </div> </template> <script> // 导入模块化样式 import styles from './styles.module.scss' export default { computed: { $style() { return styles // 暴露给模板使用 } } } </script> <style module lang="scss"> /* 直接使用模块化语法 */ .container { color: $primary-color; background: url('@/assets/bg.png'); } </style> ``` ### 验证配置是否生效 1. 创建测试文件 `test.module.scss`: ```scss .container { color: red; &:hover { color: blue; } } ``` 2. 在 JS 中导入并检查类名映射: ```javascript import styles from './test.module.scss'; console.log(styles); // 输出: { container: "_container_1x9b8_1", ... } ``` 3. 检查生成的 HTML 类名: ```html <div class="_container_1x9b8_1">...</div> ``` ### 注意事项 1. **避免混合使用**:不要在同一个项目中同时使用 `import 'file.scss'` `import styles from 'file.module.scss'` 2. **路径处理**:确保在 CSS 中使用的资源路径(如图片)能正确解析,添加 `~` 前缀表示模块路径: ```scss .icon { background: url(~@/assets/icon.png); /* 正确 */ // background: url(@/assets/icon.png); /* 可能解析失败 */ } ``` 3. **全局变量**:如需在模块化 SCSS 中使用全局变量,在 Webpack 配置中添加: ```javascript { loader: 'sass-loader', options: { additionalData: `@import "@/styles/variables.scss";` } } ``` ### 相关问题 1. 如何在 CSS Modules 中组合多个类名? 2. 使用 CSS Modules 时如何处理第三方库的样式? 3. 如何配置 CSS Modules 的类名生成规则? 4. 在 Vue 单文件组件中如何同时使用全局局部样式? 5. CSS Modules 与 Scoped CSS 的主要区别是什么? [^1]: Webpack 模块规则配置基础 [^2]: Webpack 插件添加方法 [^5]: 样式加载器冲突解决方案
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值