# 打包图片

src/index.js

import avatar from '../assets/img/clock.svg'

const root = document.getElementById('root')
const img = document.createElement('img')

img.src = avatar
root.appendChild(img)

运行打包命令 npx webpack,发现终端报错了。

Webapck 默认只能处理 JS 文件,如果想处理非 JS 文件,则需要使用 loader。

什么是loader呢?

loader是一种打包规则,它告诉了 Webpack 在遇到非.js文件时,应该如何处理这些文件

loader 的使用规则:

  • 使用test正则来匹配相应的文件
  • 使用use来添加文件对应的loader
  • 对于多个loader而言,从 右到左 依次调用

下面我们来处理上面的报错。

安装 file-loader

npm install file-loader --save-dev

修改 webpack.config.js 文件










 
 
 
 
 
 
 
 
 
 
 
 


const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: 'file-loader',
          }
        ]
      }
    ]
  }
}

再次运行 npx webpack 命令,在浏览器开发 dist 目录下的 index.html 文件,图片正常显示了。

打包前图片的名字是 clock.svg , 打包后的文件名是 f73801df10540624f3efb030442f6132.svg ,文件名换成了一串字符串。

只看这个字符串我们并不知道这个图片文件是哪个图片,我们可以通过 占位符 来解决。

常用占位符:

  • [name] - 原来的文件的名字
  • [ext] - 原本文件的后缀
  • [hash] - 一个md5的唯一编码

对 webpack.config.js 文件进行如下修改

















 
 
 







const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash].[ext]'
            }
          }
        ]
      }
    ]
  }
}

重新打包后的文件名为 clock_f73801df10540624f3efb030442f6132.svg 。

# 打包样式文件

src/index.css

body {
  background-color: red;
}

src/index.js

import './index.css'

终端运行 npx webpack命令后,会报如下错误:

安装 style-loader 和 css-loader

npm install --save-dev style-loader css-loader

修改 webpack.config.js 文件










 
 
 
 
 
 
 
 


const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      }
    ]
  }
}

重新运行 npx webpack 命令,浏览器中运行 dist/index.html 文件,结果如下:

上面我们使用 loader 打包了 css 文件,但是在我们实际写项目的时候,除了这种纯 css 文件外还有less、sass、styl等等,每一种都需要不同的loader来处理,简单总结如下:

  • 普通.css文件,使用style-loader和css-loader来处理
  • .less文件,使用less-loader来处理
  • .sass或者.scss文件,需要使用sass-loader来处理
  • .styl文件,需要使用stylus-loader来处理

# 打包Scss文件

npm install sass-loader sass webpack --save-dev

webpack.config.js












 
 
 
 




const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: ["style-loader", "css-loader", "sass-loader"],
      }
    ]
  }
}

src/index.scss

body {
  background-color: blue;
}

src/index.js

import './index.scss'

打包后的运行结果:

# 样式添加前缀

安装

npm install --save-dev postcss-loader postcss autoprefixer

新建 postcss.config.js 文件,并将如下代码粘贴进去

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}

如果 autoprefixer 没有生效,可以在 package.json 文件中配置浏览器

"browserslist": [
  "defaults",
  "last 2 versions"
]

或者在根目录创建 .browserslistrc 文件

defaults
last 2 versions

如果使用的是 Stylus 预处理器,postcss-loader 可能会识别不出来 Stylus 省略花括号的情况。这个时候需要我们把 postcss-loader 移到 stylus-loader 的前面

{
  test: /\.styl$/,
  use: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader']
}

# 模块化打包css

Css模块打包可以这样这样理解:各个模块间样式相互独立,除非主动引用,否则打包的样式不能互相影响。

src/index.scss

.clock {
  width: 20px;
}

src/showClock.js

import clock from '../assets/img/clock.svg'

export function showClock() {
  const img = new Image()
  img.src = clock
  img.classList.add('clock')
  
  const root = document.getElementById('root')
  root.appendChild(img)
}

src/index.js

import './index.scss'
import { showClock } from './showClock'
import clock from '../assets/img/clock.svg'

showClock()

const img = new Image()
img.src = clock
img.classList.add('clock')

const root = document.getElementById('root')
root.appendChild(img)

打包后的运行结果:

可以看到 showClock.js 文件中创建的图片样式被 index.js 文件引入的 index.scss 中的 .clock 样式影响了。

如果我们想去除这种影响,需要开启对css样式文件的模块化打包。


























 
 
 
 
 
 






const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash].[ext]'
            }
          }
        ]
      },
      {
        test: /\.s[ac]ss$/i,
        use: ["style-loader", 
        {
          loader: "css-loader",
          options: {
            modules: true
          }
        },
        "sass-loader", "postcss-loader"],
      }
    ]
  }
}

src/index.js

 







 




import style from './index.scss'
import { showClock } from './showClock'
import clock from '../assets/img/clock.svg'

showClock()

const img = new Image()
img.src = clock
img.classList.add(style['clock'])

const root = document.getElementById('root')
root.appendChild(img)

打包后的运行结果: