webpack成长指北第6章---webpack的图片引入

webpack成长指北第6章---webpack的图片引入

  • 案例
    • 项目目录
    • 代码
    • 打包
  • loader
    • url-loader
      • 安装url-loader
      • 配置webpack
      • url-loader的limit

案例

我们先尝试一下直接引入图片然后打包项目,看看是什么情景

项目目录

webpack成长指北第6章---webpack的图片引入_第1张图片

代码

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- 解决没有favicon.ico时报错GET http://localhost:9999/favicon.ico 404 (Not Found) -->
  <link rel="shortcut icon" href="#" />
  <title>webpack学习</title>
</head>
<body>
  <div>这是webpack学习</div>
  <div id="root"></div>
  <script src="./dist/main.js"></script>
</body>
</html>

index.js

const starImg = require('./src/assets/star.png');

const dom = document.getElementById('root');
const imgBox = new Image();
imgBox.src = starImg;
dom.append(imgBox);

webpack.config.js

const path = require('path'); // 由于webpack无法直接操作文件夹,所以需要引入node的path模块

module.exports = {
  // entry: './index.js', // 指定当前目录的index.js为打包的入口文件
  entry: {
    main: './index.js', // 指定当前目录的index.js为打包的入口文件
                       // 实际上是 entry: './index.js' 的具体写法,main为打包的Chunk Name
    // sub: './postcss.config.js', // 可以有多个入口文件,指定当前目录的postcss.config.js为打包的入口文件
  },
  mode: 'development', // mode  指定打包模式(development(不会被压缩),production(这个模式的话代码会被压缩))
                       // development默认配置了sourcemap
                       // development默认无tree shaking配置,需要额外配置
  output: {
    // filename: '[name].[contenthash].js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
    // chunkFilename: '[name].[contenthash].chunk.js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
    filename: '[name].js', // 打包后输出的打包文件的文件名,根据entry的chunk name作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
    // filename: '[name].[chunkhash].js', // 打包后输出的打包文件的文件名,根据entry的chunk name + chunkhash(解决缓存不更新的问题)作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
    // chunkFilename: '[name].chunk.js', // 入口文件走filename,其他非入口文件是index.js引入(同步引入或者异步引入)的间接js文件(非入口文件),如果打包生成的间接js文件,是走chunkFilename
    path: path.resolve(__dirname, 'dist'), // 指定打包后输出的打包文件在当前webpack.config.js所在文件夹的绝对路径的dist文件夹下
                                           // path值必须是绝对路径 ,所以引入path包,__dirname代表当前webpack.config.js所在文件夹的绝对路径
                                           // 整体路径为第一个参数+第二个参数,即__dirname + dist
                                           // 是所有输出文件的目标路径(物理路径, 存储路径);                  
    publicPath: '/'   // (url 相对于 HTML 页面所在文件夹的绝对路径 + 值)给output配置全局的publicPath,
                          // 这样各个loader打包出来的文件发布路径(引用地址)就是此全局publicPath + loader的options.outputPath
                          // (文件引用路径就是看这个)
                          // 是对页面引入资源的补充,比如img标签引入或者css引入等.
                          // 千万不能设错,应该观察文件和HTML页面的存储地址位置,进行设置,否则引用时地址会错误,找不到文件
    // publicPath: 'http://www.cdn.cn' // 如果,想把打包后生成的index.html作为入口文件,而打包生成的js放到服务器上如http://www.cdn.cn,那么webpack就应该这样设置
  }
}

package.json

{
  "name": "01_why_use",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "bundle": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11"
  }
}

打包

执行npm run bundle
打包结果如下,报错了,提示我们需要通过一个loader来处理star.png图片
webpack成长指北第6章---webpack的图片引入_第2张图片

loader

在编写前端页面的时候,我们总是时常需要引入一些图片进行展示,那么如何利用webpack将图片打包进我们的项目中呢?

webpack默认是可以处理js文件的,但是它不能直接处理jpg,gif,png图片等静态资源,因此我们需要可以处理jpg,gif,png图片等静态资源的loader

loader就是一个打包方案,对于特定文件,loader可以告诉webpack如何打包这些文件,webpack不识别非js结尾的文件,就需要loader告诉webpack如何打包这些文件(如果需要打包的文件不是以js为后缀,就要考虑使用loader了

在更高层面,webpack的loader有两个属性
test属性:用于标识出应该被对应的loader进行转换的某个或某些文件
use属性:表示进行转换时,应该使用哪个loader

url-loader

我们可以通过url-loader或者file-loader进行图片的打包处理,这里我们以url-loader为例

安装url-loader

npm i url-loader file-loader -D

配置webpack

webpack.config.js

const path = require('path'); // 由于webpack无法直接操作文件夹,所以需要引入node的path模块

module.exports = {
  // entry: './index.js', // 指定当前目录的index.js为打包的入口文件
  entry: {
    main: './index.js', // 指定当前目录的index.js为打包的入口文件
                       // 实际上是 entry: './index.js' 的具体写法,main为打包的Chunk Name
    // sub: './postcss.config.js', // 可以有多个入口文件,指定当前目录的postcss.config.js为打包的入口文件
  },
  mode: 'development', // mode  指定打包模式(development(不会被压缩),production(这个模式的话代码会被压缩))
                       // development默认配置了sourcemap
                       // development默认无tree shaking配置,需要额外配置
  module: {
    rules: [
      {
        test: /\.(jpg|png|gif)$/, // 对文件类型后缀进行匹配
        use: {
          loader: 'url-loader', // 使用url-loader对图片进行打包,如果url-loader的options没有设置limit,默认将所有静态文件全部打包成base64的字符串放到js里
          options: {
            name: '[name]_[hash].[ext]', // 输出的文件名为[原名称]_[哈希值].[原后缀]
            outputPath: 'images/',       // 文件存储路径(output.path + 值)(物理路径, 存储路径)
                                        // 负责输出目录, 即打包后的写在磁盘的位置
          }
        }
      },
    ]
  },
  output: {
    // filename: '[name].[contenthash].js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
    // chunkFilename: '[name].[contenthash].chunk.js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
    filename: '[name].js', // 打包后输出的打包文件的文件名,根据entry的chunk name作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
    // filename: '[name].[chunkhash].js', // 打包后输出的打包文件的文件名,根据entry的chunk name + chunkhash(解决缓存不更新的问题)作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
    // chunkFilename: '[name].chunk.js', // 入口文件走filename,其他非入口文件是index.js引入(同步引入或者异步引入)的间接js文件(非入口文件),如果打包生成的间接js文件,是走chunkFilename
    path: path.resolve(__dirname, 'dist'), // 指定打包后输出的打包文件在当前webpack.config.js所在文件夹的绝对路径的dist文件夹下
                                           // path值必须是绝对路径 ,所以引入path包,__dirname代表当前webpack.config.js所在文件夹的绝对路径
                                           // 整体路径为第一个参数+第二个参数,即__dirname + dist
                                           // 是所有输出文件的目标路径(物理路径, 存储路径);                  
    publicPath: '/'   // (url 相对于 HTML 页面所在文件夹的绝对路径 + 值)给output配置全局的publicPath,
                          // 这样各个loader打包出来的文件发布路径(引用地址)就是此全局publicPath + loader的options.outputPath
                          // (文件引用路径就是看这个)
                          // 是对页面引入资源的补充,比如img标签引入或者css引入等.
                          // 千万不能设错,应该观察文件和HTML页面的存储地址位置,进行设置,否则引用时地址会错误,找不到文件
    // publicPath: 'http://www.cdn.cn' // 如果,想把打包后生成的index.html作为入口文件,而打包生成的js放到服务器上如http://www.cdn.cn,那么webpack就应该这样设置
  }
}
  • npm run bundle,打包
    发现报错了,资源引用路径变成了[object Module]
    webpack成长指北第6章---webpack的图片引入_第3张图片
    webpack成长指北第6章---webpack的图片引入_第4张图片
    这是因为新版本url-loader 的esModule默认为true,会导致图片的地址变为[object Module],因此这里设置为false(备注:如果是使用file-loader打包图片,也会碰到同样的文件,用同样的解决办法即可)
    修改webpack.config.js
const path = require('path'); // 由于webpack无法直接操作文件夹,所以需要引入node的path模块

module.exports = {
  // entry: './index.js', // 指定当前目录的index.js为打包的入口文件
  entry: {
    main: './index.js', // 指定当前目录的index.js为打包的入口文件
                       // 实际上是 entry: './index.js' 的具体写法,main为打包的Chunk Name
    // sub: './postcss.config.js', // 可以有多个入口文件,指定当前目录的postcss.config.js为打包的入口文件
  },
  mode: 'development', // mode  指定打包模式(development(不会被压缩),production(这个模式的话代码会被压缩))
                       // development默认配置了sourcemap
                       // development默认无tree shaking配置,需要额外配置
  module: {
    rules: [
      {
        test: /\.(jpg|png|gif)$/, // 对文件类型后缀进行匹配
        use: {
          loader: 'url-loader', // 使用url-loader对图片进行打包,如果url-loader的options没有设置limit,默认将所有静态文件全部打包成base64的字符串放到js里
          options: {
          	esModule: false, // 新版本中esModule默认为true,会导致图片的地址变为[object Module],因此这里设置为false
            name: '[name]_[hash].[ext]', // 输出的文件名为[原名称]_[哈希值].[原后缀]
            outputPath: 'images/',       // 文件存储路径(output.path + 值)(物理路径, 存储路径)
                                        // 负责输出目录, 即打包后的写在磁盘的位置
          }
        }
      },
    ]
  },
  output: {
    // filename: '[name].[contenthash].js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
    // chunkFilename: '[name].[contenthash].chunk.js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
    filename: '[name].js', // 打包后输出的打包文件的文件名,根据entry的chunk name作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
    // filename: '[name].[chunkhash].js', // 打包后输出的打包文件的文件名,根据entry的chunk name + chunkhash(解决缓存不更新的问题)作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
    // chunkFilename: '[name].chunk.js', // 入口文件走filename,其他非入口文件是index.js引入(同步引入或者异步引入)的间接js文件(非入口文件),如果打包生成的间接js文件,是走chunkFilename
    path: path.resolve(__dirname, 'dist'), // 指定打包后输出的打包文件在当前webpack.config.js所在文件夹的绝对路径的dist文件夹下
                                           // path值必须是绝对路径 ,所以引入path包,__dirname代表当前webpack.config.js所在文件夹的绝对路径
                                           // 整体路径为第一个参数+第二个参数,即__dirname + dist
                                           // 是所有输出文件的目标路径(物理路径, 存储路径);                  
    publicPath: '/'   // (url 相对于 HTML 页面所在文件夹的绝对路径 + 值)给output配置全局的publicPath,
                          // 这样各个loader打包出来的文件发布路径(引用地址)就是此全局publicPath + loader的options.outputPath
                          // (文件引用路径就是看这个)
                          // 是对页面引入资源的补充,比如img标签引入或者css引入等.
                          // 千万不能设错,应该观察文件和HTML页面的存储地址位置,进行设置,否则引用时地址会错误,找不到文件
    // publicPath: 'http://www.cdn.cn' // 如果,想把打包后生成的index.html作为入口文件,而打包生成的js放到服务器上如http://www.cdn.cn,那么webpack就应该这样设置
  }
}

重新npm run bundle打包
图片成功出现
webpack成长指北第6章---webpack的图片引入_第5张图片
但是发现打包生成的dist没有图片文件,这是怎么回事呢?
webpack成长指北第6章---webpack的图片引入_第6张图片
看一下打包生成的main.js,原来url-loader将图片转成了base64字符串,放到了main.js里
webpack成长指北第6章---webpack的图片引入_第7张图片

url-loader的limit

正常情况下,小图片我们为了减少http请求次数,可以将其打包进main.js里,但是如果图片过大,放到main.js反而会影响页面打开的速度,因此我们最好做一个限制,超出限制大小的图片,则将其打包到一个image文件夹里,未超出限制大小,则将图片转成base64打包进main.js里。url-loader恰好有这个功能
webpack.config.js增加url-loader的limit

rules: [
      {
        test: /\.(jpg|png|gif)$/, // 对文件类型后缀进行匹配
        use: {
          loader: 'url-loader', // 使用url-loader对图片进行打包,如果url-loader的options没有设置limit,默认将所有静态文件全部打包成base64的字符串放到js里
          options: {
            esModule: false, // 新版本中esModule默认为true,会导致图片的地址变为[object Module],因此这里设置为false
            name: '[name]_[hash].[ext]', // 输出的文件名为[原名称]_[哈希值].[原后缀]
            outputPath: 'images/',       // 文件存储路径(output.path + 值)(物理路径, 存储路径)
                                        // 负责输出目录, 即打包后的写在磁盘的位置
            limit: 2048                 // 限制当文件小于2KB的时候,就将文件转为base64存储于js中,以减少http请求次数,当文件大于2KB,则打包文件到指定目录,避免js过大
          }
        }
      },
    ]

重新npm run bundle打包,可以看到dist目录生成了images目录和一张图片
但是打开index.html,提示图片路径出错了
webpack成长指北第6章---webpack的图片引入_第8张图片
上一篇文章webpack成长指北第5章—webpack的基础配置讲过,output.publicPath是对页面引入资源的补充,比如img标签引入或者css引入等,一般来说,如果打包本地资源报404,很有可能就是publicPath没设置正确导致的,我们修改一下webpack的output.publicPath

output: {
    filename: '[name].[contenthash].js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
    path: path.resolve(__dirname, 'dist'), // 指定打包后输出的打包文件在当前webpack.config.js所在文件夹的绝对路径的dist文件夹下
                                           // path值必须是绝对路径 ,所以引入path包,__dirname代表当前webpack.config.js所在文件夹的绝对路径
                                           // 整体路径为第一个参数+第二个参数,即__dirname + dist
                                           // 是所有输出文件的目标路径(物理路径, 存储路径);                  
    publicPath: './dist/'   // (url 相对于 HTML 页面所在文件夹的绝对路径 + 值)给output配置全局的publicPath,
                          // 这样各个loader打包出来的文件发布路径(引用地址)就是此全局publicPath + loader的options.outputPath
                          // (文件引用路径就是看这个)
                          // 是对页面引入资源的补充,比如img标签引入或者css引入等.
                          // 千万不能设错,应该观察文件和HTML页面的存储地址位置,进行设置,否则引用时地址会错误,找不到文件
  }

再次打包,运行成功,图片成功展示
webpack成长指北第6章---webpack的图片引入_第9张图片
如有问题,欢迎探讨,谢谢。

你可能感兴趣的:(webpack成长指北)