当我们在一个文件中引入一个CSS文件,然后去 npm run build 的时候又会报错,这是因为前面说过Webpack默认只认识JS文件,所以我还需要安装一些loader去处理CSS这样的样式文件。

  1. .avatar {
  2. width: 200px;
  3. height: 200px;
  4. }
  1. import imgUrl from "../static/demo.jpg";
  2. import './index.css';
  3. function creatAvatar() {
  4. var img = new Image();
  5. img.src = imgUrl;
  6. img.classList.add("avatar");
  7. var app = document.getElementById("app");
  8. app.append(img);
  9. }
  10. export default creatAvatar;

style-loader 和 css-loader

style-loader | webpack 中文文档
css-loader | webpack 中文文档

首先我们需要安装两个Loader

  1. $ npm install style-loader css-loader --save-dev

进行配置:

  1. module.exports = {
  2. // ...
  3. module: {
  4. rules: [
  5. {
  6. test: /\.jpg$/,
  7. use: {
  8. loader: "url-loader",
  9. options: {
  10. // 如果图片小于2048(2kb)字节的话就处理成base64的字符串
  11. limit: 2048
  12. }
  13. }
  14. },
  15. {
  16. test: /\.css$/,
  17. // 当使用多个loader 的时候可以用数组(从后向前执行),先执行 css-loader 再执行 style-loader
  18. use: ["style-loader", "css-loader"]
  19. }
  20. ]
  21. }
  22. }

JS文件看到.css文件就会根据module中的loadercss文件进行打包。
现在我们来改动一下:

  1. .avatar {
  2. width: 200px;
  3. height: 200px;
  4. }
  1. @import './avatar.css'
  1. import './index.css';
  2. // ...

JS文件不变,继续引入index.css,然后执行 npm run build 打包依然是正常。 :::info 这是因为css-loader会帮我们分析出几个css文件之间依赖的关系,把多个css文件合并为一段css
style-loader得到css-loader处理后的结果把css代码挂载到页面的head标签中 。 ::: image.png
所以**css-loader****style-loader**必须连起来使用。

如何使用 scss/less

style-loader | webpack 中文文档

我们接着修改文件:

  1. /* 重命名index.css ==> index.scss */
  2. body {
  3. .avatar {
  4. width: 200px;
  5. height: 200px;
  6. }
  7. }
  1. import imgUrl from "../static/demo.jpg";
  2. import './index.scss';
  3. // ...

当我们运行npm run build 的时候肯定报错,这是因为Webpack又不认识.scss文件了。
然后我们修改配置文件webpack.config.js

  1. module.exports = {
  2. // ...
  3. module:{
  4. rules: [
  5. {
  6. test: /\.jpg$/,
  7. use: {
  8. loader: "url-loader",
  9. options: {
  10. limit: 2048
  11. }
  12. }
  13. },
  14. {
  15. test: /\.scss$/,
  16. use: ["style-loader", "css-loader"]
  17. }
  18. ]
  19. }
  20. }

这样虽然能编译成功,但是css的样式却没有效果,这是因为scss的语法并没有被编译:
image.png
所以我要安装sass-loader

  1. $ npm install sass-loader node-sass --save-dev

修改配置文件:

  1. module.exports = {
  2. // ...
  3. module:{
  4. rules: [
  5. {
  6. test: /\.jpg$/,
  7. use: {
  8. loader: "url-loader",
  9. options: {
  10. limit: 2048
  11. }
  12. }
  13. },
  14. {
  15. test: /\.scss$/,
  16. // 执行的顺序 sass-loader的结果- css-loader的结果- style-loader,所以是从后往前的执行顺序
  17. use: ["style-loader", "css-loader","sass-loader"]
  18. }
  19. ]
  20. }
  21. }

这个时候再运行就可以编译了。

使用 postcss-loader

postcss-loader | webpack 中文文档

现在我们给.avatar添加一个CSS3的属性:

  1. body {
  2. .avatar {
  3. width: 200px;
  4. height: 200px;
  5. transform: translate(100px);
  6. }
  7. }

我们编译后发现图片确实进行位移了,但是却没有浏览器兼任的前缀(部分浏览器需要兼容CSS3的新属性)。
image.png

我们可以使用 postcss-loader 来解决这个问题。
安装:

  1. # 安装 postcss-loader
  2. $ npm install postcss-loader -D
  3. # 还需要安装一个postcss 的插件
  4. $ npm install autoprefixer -D

配置:

  1. module.exports = {
  2. // ...
  3. module:{
  4. rules: [
  5. {
  6. test: /\.jpg$/,
  7. use: {
  8. loader: "url-loader",
  9. options: {
  10. limit: 2048
  11. }
  12. }
  13. },
  14. {
  15. test: /\.scss$/,
  16. // 执行的顺序 sass-loader 的结果 css-loader 的结果 style-loader,所以是从后往前的执行顺序
  17. use: ["style-loader", "css-loader", "sass-loader", "postcss-loader"]
  18. }
  19. ]
  20. }
  21. }

另外还需要新加一个postcss的配置文件postcss.config.js(和webpack.config.js一样,配置文件名不能进行更改,Loader将会自动搜索配置文件)。

  1. module.exports = {
  2. // 插件 plugins 可以是对象或者数组
  3. plugins: [
  4. // 给css3的新属性添加浏览器兼容(比如:-webkit-)
  5. require("autoprefixer")
  6. ]
  7. }

如果不生效则可能是当前浏览器版本已经足够支持CSS3的属性,所以不会新增浏览器前缀,如果确实想要进行拼接,可以在package.json文章中新增如下配置:

  1. {
  2. "scripts": {
  3. "build": "webpack"
  4. },
  5. // 新增 browserslist 属性告知浏览器的版本
  6. "browserslist": [
  7. "> 1%",
  8. "last 2 versions"
  9. ],
  10. "devDependencies": {
  11. "autoprefixer": "^10.4.13",
  12. "css-loader": "^5.2.7",
  13. "file-loader": "^6.2.0",
  14. "postcss-loader": "^4.2.0",
  15. "style-loader": "^2.0.0",
  16. "url-loader": "^4.1.1",
  17. "webpack": "^4.41.2",
  18. "webpack-cli": "^3.3.10"
  19. }
  20. }

配置具体的 css-loader

module.rules.use.loader 除了用数组字符串的形式,还可以使用数组对象的方式。

  1. module.exports = {
  2. // ...
  3. module:{
  4. rules: [
  5. {
  6. test: /\.jpg$/,
  7. use: {
  8. loader: "url-loader",
  9. options: {
  10. limit: 2048
  11. }
  12. }
  13. },
  14. {
  15. test: /\.scss$/,
  16. // 执行的顺序 sass-loader 的结果 css-loader 的结果 style-loader,所以是从后往前的执行顺序
  17. use: [
  18. "style-loader",
  19. {
  20. loader: "css-loader",
  21. options: {
  22. // 表示仍然要继续从 postcss-loader 开始执行
  23. importLoaders: 2
  24. }
  25. }, "sass-loader", "postcss-loader"
  26. ]
  27. }
  28. ]
  29. }
  30. }
  1. @import "./test.scss";
  2. /* Webpack 的某些版本在 index.js 文件引入 index.scss 的时候已经执行到 css-loader 了,
  3. 如果 index.scss 文件又引入了 test.scss 文件就会出现解析问题 */
  4. body {
  5. .avatar {
  6. width: 200px;
  7. height: 200px;
  8. transform: translate(100px);
  9. }
  10. }

webpack.config.js配置文件中,如果不配置importLoaders的话,在index.scss文件中引入test.scss文件就不会从postcss-loadersass-loader进行编译。

CSS 模块化

当我们在同一个JS文件中创建两个照片,就像这样:

  1. import creatAvatar from './creatAvatar';
  2. import creatAvatar02 from './creatAvatar02';
  3. import './index.scss';
  4. creatAvatar();
  5. creatAvatar02();
  1. import imgUrl from "../static/demo.jpg";
  2. function creatAvatar() {
  3. var img = new Image();
  4. img.src = imgUrl;
  5. img.classList.add("avatar");
  6. var app = document.getElementById("app");
  7. app.append(img);
  8. }
  9. export default creatAvatar;
  1. import imgUrl from "../static/demo.jpg";
  2. function creatAvatar() {
  3. var img = new Image();
  4. img.src = imgUrl;
  5. img.classList.add("avatar");
  6. var app = document.getElementById("app");
  7. app.append(img);
  8. }
  9. export default creatAvatar;

image.png
这个时候index.js文件引入的scss文件就成了全局的样式文件,影响着页面全部的图片。
我们可以在weboack.config.js文件中对css-loader进行配置实现隔离模块化:

  1. moduele.exports = {
  2. // ...
  3. mode:{
  4. rules:[{
  5. test: /\.scss$/,
  6. use: [
  7. "style-loader",
  8. {
  9. loader: "css-loader",
  10. options: {
  11. importLoaders: 2,
  12. // 实现样式模块化
  13. modules: true
  14. }
  15. },
  16. "sass-loader",
  17. "postcss-loader"
  18. ]
  19. }]
  20. }
  21. }
  1. import header from './header'
  2. import footer from './footer'
  3. import creatAvatar from './creatAvatar';
  4. import creatAvatar02 from './creatAvatar02';
  5. creatAvatar();
  6. creatAvatar02();
  1. import imgUrl from "../static/demo.jpg";
  2. import style from './index.scss';
  3. function creatAvatar() {
  4. var img = new Image();
  5. img.src = imgUrl;
  6. img.classList.add(style.avatar);
  7. var app = document.getElementById("app");
  8. app.append(img);
  9. }
  10. export default creatAvatar;
  1. import imgUrl from "../static/demo.jpg";
  2. function creatAvatar() {
  3. var img = new Image();
  4. img.src = imgUrl;
  5. img.classList.add("avatar");
  6. var app = document.getElementById("app");
  7. app.append(img);
  8. }
  9. export default creatAvatar;

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