Img srcset 的大小无法按预期工作,响应式下一个/图像在 Chromium 的模拟移动屏幕上发送

LHC*_*LHC 10 javascript reactjs webpack next.js nextjs-image

我做了什么?

next/image设置 NextJs 项目,借助具有以下设置的组件为不同的屏幕尺寸提供不同的图像尺寸:

<Image
  src={image}
  alt={title}
  objectFit='cover'
  layout='responsive'
  placeholder='blur'
  width={320}
  height={240}
  sizes={width !== undefined ? `${Math.round(width)}px` : '100vw'}
/>
Run Code Online (Sandbox Code Playgroud)

我期待什么?

所提供的图像在 Chromium DevTools 中指定了sizes桌面和移动视图。对于桌面视图,这似乎按预期工作。从图像的固有宽度分辨率 (512px) 和渲染宽度分辨率 (492px) 中可以看出。 桌面视图屏幕截图

发生了什么?

由于某种原因我无法弄清楚,Chromium 中的移动视图不会发生这种情况。这里,固有宽度分辨率为 1024px,尽管渲染分辨率也是 492px。 Mobile-View-Screenshot 老实说,我并不完全理解 next.config.js 设备和屏幕尺寸与 next/image 组件的尺寸和布局设置有何关系。希望论坛里的高人能赐教一下。

一般应用设置

应用程序堆栈

在专用的 Debian 机器上使用 docker-compose 来与 NextJs、Mongodb 和其他一些微服务(例如 Redis)和具有 Fast-API 的 Python Worker 一起进行暂存。

next.config.js

const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})

const withCss = require('@zeit/next-css')
const withPurgeCss = require('next-purgecss')

const { PHASE_DEVELOPMENT_SERVER } = require('next/constants')

const nextConfig = {
  webpack(config) {
    const fileLoaderRule = config.module.rules.find(
      (rule) => rule.test && rule.test.test('.svg')
    )
    fileLoaderRule.exclude = /\.svg$/
    config.module.rules.push({
      test: /\.svg$/,
      loader: require.resolve('@svgr/webpack'),
    })
    return config
  },
}

nextConfig.i18n = {
  locales: ['de-DE', 'en-US', 'ja-JP'],
  defaultLocale: 'de-DE',
}

nextConfig.images = {
  deviceSizes: [
    256, 320, 492, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1664, 1792,
    1920, 2048, 2176, 2304, 2432, 2560, 2688, 2944,
  ],
  imageSizes: [32, 64, 96, 112, 128, 144, 160, 176, 192, 240],
  formats: ['image/avif', 'image/webp'],

  domains: [
    'upload.wikimedia.org',
    'wikimedia.org',
    'i.ytimg.com',
  ],
}

module.exports = (phase) => {
  if (process.env.PURGE_CSS === 'true') {
    return withCss(withPurgeCss(nextConfig))
  }
  if (phase === PHASE_DEVELOPMENT_SERVER) {
    return nextConfig
  }
  return nextConfig
}

module.exports = (phase) => {
  if (process.env.ANALYZE === 'true') {
    return withBundleAnalyzer(nextConfig)
  }
  if (phase === PHASE_DEVELOPMENT_SERVER) {
    return nextConfig
  }
  return nextConfig
}
Run Code Online (Sandbox Code Playgroud)

下一个/图像元素

在 Card 元素中的图像上,我设置大小以生成 scrset,该 scrset 为不同的屏幕尺寸提供或多或少合适的图像尺寸。

内容卡.jsx

import Image from 'next/image'
import Link from 'next/link'

import styles from './ContentCard.module.css'

import dynamic from 'next/dynamic'
import useDimensions from 'react-cool-dimensions';
const ArrowRightIcon = dynamic(() => import('@/assets/icons/arrow-right-icon'), {ssr: false})

function ContentCard({ title, claim, image, action, href }) {
  const { observe, width } = useDimensions();
  return (
    <div className={styles.item}>
      <Link passHref href={href}>
        <a>
          <div>
            <div ref={observe} className={styles.image}>
              <Image
                src={image}
                alt={title}
                objectFit='cover'
                layout='responsive'
                placeholder='blur'
                width={320}
                height={240}
                sizes={width !== undefined ? `${Math.round(width)}px` : '100vw'}
              />
            </div>

            <div className={styles.content}>
              <div className={styles.title}>
                <h3>{title}</h3>
              </div>
              <p>{claim}</p>
              <div className={styles.actions}>
                <span className={styles.icon}>
                  {action}&emsp;
                  <ArrowRightIcon />
                </span>
              </div>
            </div>
          </div>
        </a>
      </Link>
    </div>
  )
}

export default ContentCard

Run Code Online (Sandbox Code Playgroud)

ContentCar.module.css

.item {
  display: inline-block;
  width: 100%;
  height: 100%;
  /* height: 400px; */
  overflow: hidden;
  transition: 0.5s all;
  position: relative;
  text-align: left;

}

.item a:link {
  color: white;
  text-decoration: none;
}

/* visited link */

.item a:visited {
  color: white;
}

/* mouse over link */

.item:hover p {
  display: flex;
}

.item:hover .content {
  transition: 0.5s all;
  font-size: larger;
  height: 75%;
}

.item:hover .title {
  transition: 0.5s all;
  font-size: larger;
  height: 50%;
}

.item:hover .actions {
  transition: 0.5s all;
  display: flex;
  height: 25%;
}

/* selected link */

.item a:active {
  color: white;
}

.content {
  position: absolute;
  bottom: 0;
  background-color: var(--primary-dark);
  height: 33.33%;
  width: 100%;
  padding-left: var(--size-1);
  display: flex;
  flex-direction: column;
}

.content p {
  display: none;
  margin-top: 0;
  padding: 0 var(--size-1);
}

.title {
  text-transform: uppercase;
  font-weight: bold;
  line-height: var(--size-1);
  margin: 0;
  position: relative;
  background-color: var(--primary-dark);
  width: 100%;
  padding-left: var(--size-1);
  display: flex;
  flex-direction: column;
}


.content h3 {
  font-size: var(--size-8);
  line-height: var(--size-8);
  margin-bottom: 0;
  padding: 0;
  text-transform: uppercase;
  font-weight: bold;

  /* margin: var(--size-1) 0; */
}

.item p {
  font-weight: normal;
  font-size: var(--size-7);
  line-height: var(--size-7);
  
  margin: 0;
}

.actions {
  display: none;
  font-size: var(--size-7);
  line-height: var(--size-7);
  font-weight: bold;
}

.icon {
  margin-left: var(--size-1);
  display: inline-flex;
  justify-content: center;
  align-items: center;
}

.icon svg {
  width: var(--size-4);
  height: var(--size-4);
}
Run Code Online (Sandbox Code Playgroud)