这系列的程序码在 https://github.com/DanSnow/ironman-2020/tree/master/static-site-generator
这篇用到的图片来源,授权是 CC0 ,作者是 Snapwire
图片是网页上一个很重要的元素, Gatsby 也提供了个跟它的 GraphQL 查询搭配的图片最佳化,不过老实说那个有点复杂,我并没有打算要做一个完全一样的,这边就来做一个比较简单的实做,我们提供图片的最佳化与 lazy loading 就好
这部份会使用到 imagemin 这个 Node.js 下常用的图片最佳化的套件,不过是以 webpack loader 的形式来使用的,所以就安装:
$ yarn add --dev image-webpack-loader
然後我们要把它再包装成自己的 webpack loader ,这样我们比较好加自己额外的资讯进去,不过这边其实只有网址而已
这边写一个很简单的 webpack loader
module.exports = function () {
return `
import url from '!!${require.resolve('file-loader')}!${require.resolve('image-webpack-loader')}!${this.resource}'
export default { url }`
}
module.exports.raw = true
再来我们要解决在 Server 端载入图片的问题,我们写个程序去 hook Node.js 的 require
import Module from 'module'
export function patchRequire() {
// 保存原本的 require
const originalRequire = Module.prototype.require
// 覆写 require
Module.prototype.require = function (id) {
// 图片的地方我是用 webpack alias 来载入的,所以判断是不是 ~ 开头,不过正常应该是要判断副档名
if (id.startsWith('~')) {
return {}
}
return originalRequire.call(this, id)
}
}
这样在 Server 端载入使用者的程序才不会出错
这边用的是很简单的实作:
import React, { useEffect, useState } from 'react'
export function Image({ img }) {
// server 端就直接回传
if (!img.url) {
return <div>Loading...</div>
}
const { url } = img
const [ready, setReady] = useState(false)
useEffect(() => {
// 等待图片载完
const img = document.createElement('img')
img.addEventListener('load', () => setReady(true))
img.src = url
}, [url])
// 图片还没好也显示 Loading ,这样才跟 Server Render 的内容一样
if (!ready) {
return <div>Loading...</div>
}
// 显示图片
return <img src={img.url} />
}
其实这篇原本还想用 sharp 提供图片缩放的,只是我在安装上出了点问题,另外范例程序中还有被我注解掉的用 blurhash 当 placeholder 的实作,因为 Node.js 的图片处理速度实在是太慢了,导致重 build 非常的花时间
下一篇我想来讲 incremental build
【[网页制作证书] 】 Certificate in Website Development 全面学...
昨天我们完成了一个基本的购物流程,但程序码内有着不安全的问题,今天我们要用 .env 的形式来规避这...
今天咱们先来简单的稍为介绍一下JavaScript Array(阵列) 物件,JavaScript ...
安桌手机适用 Android 无广告 自动封锁,诈骗电话,骚扰电话,行销,广告,推销,来电未显示,不...
不足的丰富资源 未依团队性质配置的资源,会制造资源不足的假象 在IT团队最大的时候,有11人,分别是...