Jacky's blog Jacky's blog
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Jacky Wang

行到水穷处,坐看云起时
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术随笔

    • git教程
    • 前端模块化:CommonJS,AMD,CMD,ES6
    • 如何动态加载本地图片
      • 0.前言
      • 1.静态资源存放位置
      • 2.图片加载方案
        • 2.1 若文件存在public文件下,可以直接使用相对路径读取
        • 2.2 若图片存在src下,将图片等静态资源当做模块加载
        • 2.3 当使用 require 动态引入图片,会导致cannot find module 的问题
        • 2.4 使用 %PUBLIC_URL% 拼接为绝对路径
      • 本篇blog仍未解决的问题:
      • 参考资料:
      • 扩展阅读:
    • GitHub自动部署脚本
    • React生命周期详解
    • 将父组件的props作为组件的初始state的几种方案
    • webpack基础入门
    • StackOver记录:如何在function中使用redux
    • React中使用onClick时的三种性能优化
    • 思考React状态管理
    • forEach/for..in/of
    • styled-components使用记录
    • 深入理解forEach与forof
    • Node技术架构
    • Redux、Mobx状态管理杂谈
    • JS中的类型检测
    • 如何判断图片是否在可视区域
    • 如何使用图片的懒加载操作
    • JavaScript模块化:从CommonJS到AMD
    • git查看:修改用户名、密码
    • 保持数据Immutable的几种写法
    • 如何实现一个Promise.all
    • resolve(Promise对象)会多出两个微任务
    • todo_基于Mocha的测试驱动开发
    • 浏览器页面渲染机制
    • todo-响应式编程之数据劫持
    • todo-immer库的介绍
    • React-Hooks 基础原理解析
    • JS基本功
    • 函数闭包与this指针
    • 收集 DUMI 配置过程中遇到的问题
    • typescript 类型工具
    • 统一接口的导入导出
    • 网络安全:如何预防 XSS 攻击
    • 浏览器页面渲染机制【2023】
    • 跨域资源请求
    • 浏览器事件循环机制
    • 如何理解浏览器的 user agent 用户代理的含义?
  • 转载文章

  • Mac相关

  • 前端学习周报

  • 包管理工具

  • 技术随笔
  • 技术随笔
wangjiasheng
2021-10-07
目录

如何动态加载本地图片

# 0.前言

在刚开始接触 React 项目中,静态资源必须使用以 import 的方式导入。

可是,在之前的静态网页开发过程中,我们只需要以 相对路径的方式引入静态资源:

<img src="./assets/demo.png">
1

但是,当使用 npm run dev 启动本地服务器,可以发现图片资源无法得到正确的引入,甚至还有可能报跨域错误。

其实,以上的问题主要是在 React 框架中已经内置了create-react-app(cra) ,在 cra 中集成了通用性的webpack 配置,这就是造成静态资源的导入失败的原因。

# 1.静态资源存放位置

首先以 相对路径 的方式引入图片等静态资源到底读取的是什么资源?

一般图片等静态资源存放的位置有两处:public/assets、src/assets。

  • 两者的主要区别:

    两者的区别主要是在是否可以被 webpack 所处理,public文件下的内容会被原封不动地 copy 至 dist 文件夹,而 src 文件下的内容则会被 webpack 处理,

  • 常见的webpack处理有:

    1. js 文件或者 css 会被压缩并捆绑在一起,以避免额外的网络请求。

    2. 缺少文件会导致编译错误,而不是用户的404错误。

    3. webpack 会对文件进行 rename,如原有路径 '@/assets/img/banner.png',转换成了 '/static/img/banner.[chunk].png'。

      // webpack.config.js
      module.exports = {
        output: {
          filename: '[name]_[hash].js' 
          //其余占位符:Hash Chunkhash Contenthash
        }
      }
      
      1
      2
      3
      4
      5
      6
      7
    4. 比如图片,如果你的图片小于你在webpack中的 loader 下设置的 limit 大小(可配置),它会被编译成base64写在行内,从而在实际项目中减少 http 请求。

      Ps: 但是随着HTTP协议不断发展,HTTP1.1中已经默认开启了 Keep-alive长连接,HTTP2.0 又具有多路复用的特性,目前已经不是很有必要再做这种操作了。

      // 使用 url-loader 设置图片的大小
      module:{
        test: /.(jpg|png|gif)$/,
        use: {
          options: {
            name: '[name]_[hash].[ext]'
            limit: 2048
          }
        }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10

# 2.图片加载方案

# 2.1 若文件存在public文件下,可以直接使用相对路径读取

<img src="./assets/demo.png"> // 读取 public/assets/demo.png
1

其原理是:public下的文件会被原封不动地拷贝到build下,而src下的文件则被压缩至build/static,且会被rename,所以不能使用相对路径的方式导入src下的文件。

# 2.2 若图片存在src下,将图片等静态资源当做模块加载

常用的两种模块化方式 require(CMD语法)和 import(ES6语法)

关于CMD、ES6、CommonJS、AMD的请见:https://juejin.cn/post/6844903576309858318

// import 引入静态资源
import png from './assets/demo.png' // 该文件在src下
<img src={png} alt=""></img>

// require 
<img src={require("./assets/demo.png").default} alt="" ></img>
1
2
3
4
5
6
点击查看

额外补充的知识点:

  • impot 有两种使用方式:1.作为函数 2.关键字

    比较常见的是作为关键字,但是仍有几个需要注意的点,以下是几个错误示例:

    // 1. import 作为关键字,必须作用在顶部作用域
    function tryImport(){
      import flag from "./example.js"
    }
    //2. import 的变量是只读属性,无法再修改,类似加了const
    import {num} from "./example.js"
    num = 1 // 报错
    
    1
    2
    3
    4
    5
    6
    7

    import的第二种用法是作为函数,其返回的是Promise对象

    import('./assets/demo.png').then(module=>{
      console.log(module)
    })
    
    // 输出:Module {default:'/static/media/demo.0a407da5.png',}
    
    1
    2
    3
    4
    5

    从上可以看出,原本的 src 目录下的 assets/demo.png 被拷贝到 public/static/media 下,且图片的名称以 [name].[hash].png 的方式被 rename。

    此外,在打印的时候仍需注意的:

    console.log('<<<',import('./assets/aaa.png').then(module=>{console.log(module)}))
    console.log(123)
    
    1
    2

    打印次序为:

    <<< Promise {<pending>}
    123
    Module {default:'/static/media/demo.0a407da5.png',}
    
    1
    2
    3
  • ⭐️ import 关键字被设计为静态的,以便让诸如文本编辑器之类的工具能轻易判断模块有哪些信息可 用。--《深入理解ES6》

# 2.3 当使用 require 动态引入图片,会导致cannot find module的问题

现在要实现的一个大的集合中遍历去加载每一项的图片,因此我将数据存放在一个json文件中,data.json的内容如下:

[{"imagePath": "@/assets/demo.png"},
{"imagePath": "@/assets/demo.png"},
{"imagePath": "@/assets/demo.png"}]
1
2
3

若仍用 require 的方式读入:

import picJson from './data.json'
<img src={require(picJson.imagePath).default}>
1
2

则会提示:can't find moudle "@/assets/demo.png",但require("@/assets/demo.png")是能够正常导入的。


▶️ 原因是:require 是在 动态运行 时引入资源的,且加载的是webpack预编译后的文件路径;当 require 使用变量来引入图片时,React 在渲染时实际传给require 的是'@/assets/demo.png'。因此在打包结果中,根本就找不到这个图片的模块。可以用下面两个方式对其进行改进:

  1. 使用模板字符串的方式引入

    <img src={require(`${picJson.imagePath}`).default}></img>
    
    1
  2. 技巧:加上一个空字符串

    <img src={require(picJson.imagePath+"").default}></img>
    
    1

# 2.4 使用 %PUBLIC_URL% 拼接为绝对路径

这个方法有些看不懂,暂时只记录看的懂得部分:https://juejin.cn/post/6892950616977948680

  • html:

    ⭐️在public目录中有个index.html是单页面应用的基本模板,所有react生成的代码都会注入到此HTML中。所以此处可以添加一些cdn脚本或者全局的html。

    在公共目录下,你可以放字体文件、图片、svg等文件,访问这些文件最好添加 %PUBLIC_URL%作为根目录。 <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

  • Javascript:

    process.env.PUBLIC_URL

# 本篇blog仍未解决的问题:

  1. 需要再复习一下webpack的配置
  2. npm run serve和build以后再启动live-server的区别?与file://的方式打开html?有什么区别?
  3. 在测试的过程中,import 和 require 编译后的html为啥有区别?

# 参考资料:

  1. require 动态引入图片,导致cannot find module见:https://juejin.cn/post/6892950616977948680
  2. public文件夹的使用见:https://juejin.cn/post/6892950616977948680
  3. Vue如何动态加载本地图片:https://www.cnblogs.com/lvonve/p/15044160.html

# 扩展阅读:

  1. webpack学习笔记--按需加载:https://www.cnblogs.com/joyco773/p/9051401.html

  2. 按需加载2:https://www.cnblogs.com/mamimi/p/7646358.html

  3. webpack打包的多页模式(本身就是懒加载?)与单页模式,见:https://www.cnblogs.com/nangezi/p/9201226.html

    任务:看完要能说出多页模式和单页模式的优缺点?

  4. react-scripts流程及源码分析,见:https://juejin.cn/post/6844903951893004296

    这篇文章实在是太难理解了,需要预先学习好多知识点,图做的超级棒👍🏻。

  5. 阮一峰写的ES6的module模块引入:https://es6.ruanyifeng.com/#docs/module-loader

  6. 掘金中总结的很好的模块化文章:https://juejin.cn/post/6844903576309858318 5和6待总结成一篇文章

编辑 (opens new window)
#模块化#React
上次更新: 2022/04/06, 15:04:00
前端模块化:CommonJS,AMD,CMD,ES6
GitHub自动部署脚本

← 前端模块化:CommonJS,AMD,CMD,ES6 GitHub自动部署脚本→

最近更新
01
如何理解浏览器的 user agent 用户代理的含义?
11-05
02
浏览器事件循环机制
10-31
03
浏览器页面渲染机制【2023】
10-15
更多文章>
Theme by Vdoing | Copyright © 2020-2023
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式