当我们在一个文件中引入一个CSS文件,然后去 npm run build 的时候又会报错,这是因为前面说过Webpack默认只认识JS文件,所以我还需要安装一些loader去处理CSS这样的样式文件。
.avatar {width: 200px;height: 200px;}
import imgUrl from "../static/demo.jpg";import './index.css';function creatAvatar() {var img = new Image();img.src = imgUrl;img.classList.add("avatar");var app = document.getElementById("app");app.append(img);}export default creatAvatar;
style-loader 和 css-loader
style-loader | webpack 中文文档
css-loader | webpack 中文文档
首先我们需要安装两个Loader:
$ npm install style-loader css-loader --save-dev
进行配置:
module.exports = {// ...module: {rules: [{test: /\.jpg$/,use: {loader: "url-loader",options: {// 如果图片小于2048(2kb)字节的话就处理成base64的字符串limit: 2048}}},{test: /\.css$/,// 当使用多个loader 的时候可以用数组(从后向前执行),先执行 css-loader 再执行 style-loaderuse: ["style-loader", "css-loader"]}]}}
当JS文件看到.css文件就会根据module中的loader对css文件进行打包。
现在我们来改动一下:
.avatar {width: 200px;height: 200px;}
@import './avatar.css'
import './index.css';// ...
JS文件不变,继续引入index.css,然后执行 npm run build 打包依然是正常。
:::info
这是因为css-loader会帮我们分析出几个css文件之间依赖的关系,把多个css文件合并为一段css。style-loader得到css-loader处理后的结果把css代码挂载到页面的head标签中 。
:::

所以**css-loader**和**style-loader**必须连起来使用。
如何使用 scss/less
我们接着修改文件:
/* 重命名index.css ==> index.scss */body {.avatar {width: 200px;height: 200px;}}
import imgUrl from "../static/demo.jpg";import './index.scss';// ...
当我们运行npm run build 的时候肯定报错,这是因为Webpack又不认识.scss文件了。
然后我们修改配置文件webpack.config.js:
module.exports = {// ...module:{rules: [{test: /\.jpg$/,use: {loader: "url-loader",options: {limit: 2048}}},{test: /\.scss$/,use: ["style-loader", "css-loader"]}]}}
这样虽然能编译成功,但是css的样式却没有效果,这是因为scss的语法并没有被编译:
所以我要安装sass-loader:
$ npm install sass-loader node-sass --save-dev
修改配置文件:
module.exports = {// ...module:{rules: [{test: /\.jpg$/,use: {loader: "url-loader",options: {limit: 2048}}},{test: /\.scss$/,// 执行的顺序 sass-loader的结果- css-loader的结果- style-loader,所以是从后往前的执行顺序use: ["style-loader", "css-loader","sass-loader"]}]}}
这个时候再运行就可以编译了。
使用 postcss-loader
现在我们给.avatar添加一个CSS3的属性:
body {.avatar {width: 200px;height: 200px;transform: translate(100px);}}
我们编译后发现图片确实进行位移了,但是却没有浏览器兼任的前缀(部分浏览器需要兼容CSS3的新属性)。
我们可以使用 postcss-loader 来解决这个问题。
安装:
# 安装 postcss-loader$ npm install postcss-loader -D# 还需要安装一个postcss 的插件$ npm install autoprefixer -D
配置:
module.exports = {// ...module:{rules: [{test: /\.jpg$/,use: {loader: "url-loader",options: {limit: 2048}}},{test: /\.scss$/,// 执行的顺序 sass-loader 的结果 css-loader 的结果 style-loader,所以是从后往前的执行顺序use: ["style-loader", "css-loader", "sass-loader", "postcss-loader"]}]}}
另外还需要新加一个postcss的配置文件postcss.config.js(和webpack.config.js一样,配置文件名不能进行更改,Loader将会自动搜索配置文件)。
module.exports = {// 插件 plugins 可以是对象或者数组plugins: [// 给css3的新属性添加浏览器兼容(比如:-webkit-)require("autoprefixer")]}
如果不生效则可能是当前浏览器版本已经足够支持CSS3的属性,所以不会新增浏览器前缀,如果确实想要进行拼接,可以在package.json文章中新增如下配置:
{"scripts": {"build": "webpack"},// 新增 browserslist 属性告知浏览器的版本"browserslist": ["> 1%","last 2 versions"],"devDependencies": {"autoprefixer": "^10.4.13","css-loader": "^5.2.7","file-loader": "^6.2.0","postcss-loader": "^4.2.0","style-loader": "^2.0.0","url-loader": "^4.1.1","webpack": "^4.41.2","webpack-cli": "^3.3.10"}}
配置具体的 css-loader
在 module.rules.use.loader 除了用数组字符串的形式,还可以使用数组对象的方式。
module.exports = {// ...module:{rules: [{test: /\.jpg$/,use: {loader: "url-loader",options: {limit: 2048}}},{test: /\.scss$/,// 执行的顺序 sass-loader 的结果 css-loader 的结果 style-loader,所以是从后往前的执行顺序use: ["style-loader",{loader: "css-loader",options: {// 表示仍然要继续从 postcss-loader 开始执行importLoaders: 2}}, "sass-loader", "postcss-loader"]}]}}
@import "./test.scss";/* Webpack 的某些版本在 index.js 文件引入 index.scss 的时候已经执行到 css-loader 了,如果 index.scss 文件又引入了 test.scss 文件就会出现解析问题 */body {.avatar {width: 200px;height: 200px;transform: translate(100px);}}
在webpack.config.js配置文件中,如果不配置importLoaders的话,在index.scss文件中引入test.scss文件就不会从postcss-loader和 sass-loader进行编译。
CSS 模块化
当我们在同一个JS文件中创建两个照片,就像这样:
import creatAvatar from './creatAvatar';import creatAvatar02 from './creatAvatar02';import './index.scss';creatAvatar();creatAvatar02();
import imgUrl from "../static/demo.jpg";function creatAvatar() {var img = new Image();img.src = imgUrl;img.classList.add("avatar");var app = document.getElementById("app");app.append(img);}export default creatAvatar;
import imgUrl from "../static/demo.jpg";function creatAvatar() {var img = new Image();img.src = imgUrl;img.classList.add("avatar");var app = document.getElementById("app");app.append(img);}export default creatAvatar;

这个时候index.js文件引入的scss文件就成了全局的样式文件,影响着页面全部的图片。
我们可以在weboack.config.js文件中对css-loader进行配置实现隔离模块化:
moduele.exports = {// ...mode:{rules:[{test: /\.scss$/,use: ["style-loader",{loader: "css-loader",options: {importLoaders: 2,// 实现样式模块化modules: true}},"sass-loader","postcss-loader"]}]}}
import header from './header'import footer from './footer'import creatAvatar from './creatAvatar';import creatAvatar02 from './creatAvatar02';creatAvatar();creatAvatar02();
import imgUrl from "../static/demo.jpg";import style from './index.scss';function creatAvatar() {var img = new Image();img.src = imgUrl;img.classList.add(style.avatar);var app = document.getElementById("app");app.append(img);}export default creatAvatar;
import imgUrl from "../static/demo.jpg";function creatAvatar() {var img = new Image();img.src = imgUrl;img.classList.add("avatar");var app = document.getElementById("app");app.append(img);}export default creatAvatar;

这样就保证了css样式只有在文件引入后才会生效。
