【问题标题】:Deploying a next.js project on Vercel or Netlify fail with "Module not found: Can't resolve..."在 Vercel 或 Netlify 上部署 next.js 项目失败并显示“未找到模块:无法解析...”
【发布时间】:2022-02-21 01:43:29
【问题描述】:

在 Vercel 或 Netlify 上部署时出现此错误。本地构建完美运行。

知道发生了什么吗? (我是开发新手,所以可能我忘了给你一些信息)。

$ yarn build
5:07:16 PM: yarn run v1.22.10
5:07:16 PM: $ next build
5:07:17 PM: warn  - No build cache found. Please configure build caching for faster rebuilds. Read more: https://nextjs.org/docs/messages/no-cache
5:07:17 PM: info  - Checking validity of types...
5:07:20 PM: info  - Creating an optimized production build...
5:07:23 PM: warn - You have enabled the JIT engine which is currently in preview.
5:07:23 PM: warn - Preview features are not covered by semver, may introduce breaking changes, and can change at any time.
5:07:35 PM: Failed to compile.
5:07:35 PM: 
5:07:35 PM: ./components/HomeSections.js
5:07:35 PM: Module not found: Can't resolve './ContentPanel' in '/opt/build/repo/components'
5:07:35 PM: Import trace for requested module:
5:07:35 PM: ./pages/index.js
5:07:35 PM: ./components/HomeSections.js
5:07:35 PM: Module not found: Can't resolve './CoverPanel' in '/opt/build/repo/components'
5:07:35 PM: Import trace for requested module:
5:07:35 PM: ./pages/index.js
5:07:35 PM: > Build failed because of webpack errors
5:07:35 PM: error Command failed with exit code 1.
5:07:35 PM: info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
5:07:35 PM: ​
5:07:35 PM: ────────────────────────────────────────────────────────────────
5:07:35 PM:   "build.command" failed                                        
5:07:35 PM: ────────────────────────────────────────────────────────────────
5:07:35 PM: ​
5:07:35 PM:   Error message
5:07:35 PM:   Command failed with exit code 1: yarn build
5:07:35 PM: ​
5:07:35 PM:   Error location
5:07:35 PM:   In Build command from Netlify app:
5:07:35 PM:   yarn build
5:07:35 PM: ​
5:07:35 PM:   Resolved config
5:07:35 PM:   build:
5:07:35 PM:     command: yarn build
5:07:35 PM:     commandOrigin: ui
5:07:35 PM:     environment:
5:07:35 PM:       - INSIGHT_ADMIN_EMAIL
5:07:35 PM:       - NEXT_PUBLIC_DB_HOST
5:07:35 PM:       - NEXT_PRIVATE_TARGET
5:07:35 PM:     publish: /opt/build/repo/.next
5:07:35 PM:     publishOrigin: ui
5:07:35 PM:   plugins:
5:07:35 PM:     - inputs: {}
5:07:35 PM:       origin: ui
5:07:35 PM:       package: '@netlify/plugin-nextjs'
5:07:35 PM:     - inputs: {}
5:07:35 PM:       origin: ui
5:07:35 PM:       package: netlify-plugin-next-dynamic
5:07:35 PM:     - inputs: {}
5:07:35 PM:       origin: ui
5:07:35 PM:       package: netlify-plugin-cache-nextjs

我的 index.js 调用 HomeSection.js 调用 ContentPanel.js 和 CoverPanel.js

index.js

import {
  useState
} from "react";
import ReactScrollWheelHandler from "react-scroll-wheel-handler";
import useDeviceSize from "../components/hooks/useDevicesize";

import HomeSections from "../components/HomeSections";
import Layout from "../components/Layout";

export default function Home({
  homeIntro,
  studies
}) {
  const studiesNumber = studies.data.length;
  let [width, height] = useDeviceSize(); // Get window size
  const [panelScrollIndex, setPanelScrollIndex] = useState(0);
  const [scrollDirection, setScrollDirection] = useState(null);
  const [isScrolling, setIsScrolling] = useState(false);
  const [itemPosition, setItemPosition] = useState(0);
  const [position, setPosition] = useState("");

  const handleSplitPanelControlClick = (i) => {
    if (i === panelScrollIndex) {} else if (i > panelScrollIndex) {
      setItemPosition((itemPosition - height + 110) * (i - panelScrollIndex));
      setPanelScrollIndex((panelScrollIndex = i));
    } else if (i < panelScrollIndex) {
      setItemPosition((itemPosition + height - 110) * (panelScrollIndex - i));
      setPanelScrollIndex((panelScrollIndex = i));
    }
  };

  const handleScroll = (direction) => {
    setIsScrolling = true;
    if (direction === "ScrollDown" && panelScrollIndex < studiesNumber - 1) {
      setItemPosition(itemPosition - height + 110);
      setPanelScrollIndex((panelScrollIndex += 1));
      // setPosition("End");
      console.log("ITEM POSITION ====>", itemPosition);
    } else if (direction === "ScrollUp" && panelScrollIndex > 0) {
      setItemPosition(itemPosition + height - 110);
      setPanelScrollIndex((panelScrollIndex -= 1));
      console.log("ITEM POSITION ====>", itemPosition);

      // setPosition("Start");
    }
  };

  return homeIntro ? ( <
    >
    <
    ReactScrollWheelHandler upHandler = {
      (e) => handleScroll("ScrollUp")
    }
    downHandler = {
      (e) => handleScroll("ScrollDown")
    } >
    <
    Layout page = {
      "Insight AM - Accueil"
    } >
    <
    div className = "w-screen h-[calc(100vh-110px)] mt-[110px] overflow-hidden " >
    <
    HomeSections panelScrollIndex = {
      panelScrollIndex
    }
    studiesNumber = {
      studiesNumber
    }
    height = {
      height
    }
    studies = {
      studies
    }
    homeIntro = {
      homeIntro
    }
    scrollDirection = {
      scrollDirection
    }
    isScrolling = {
      isScrolling
    }
    setIsScrolling = {
      setIsScrolling
    }
    itemPosition = {
      itemPosition
    }
    position = {
      position
    }
    handleSplitPanelControlClick = {
      handleSplitPanelControlClick
    }
    /> <
    /div> <
    /Layout> <
    /ReactScrollWheelHandler> <
    />
  ) : ( <
    p > ...Loading < /p>
  );
}

export async function getStaticProps() {
  // Get home-intro content from Strapi
  const resHome = await fetch(
    `${process.env.NEXT_PUBLIC_DB_HOST}/api/home-introduction?populate=*`
  );
  const homeIntro = await resHome.json();

  // Get studies from Strapi
  const resStudies = await fetch(
    `${process.env.NEXT_PUBLIC_DB_HOST}/api/studies?populate=*`
  );
  const studies = await resStudies.json();

  return {
    props: {
      homeIntro,
      studies
    }
  };
}

HomeSection.js

import ContentPanel from "./ContentPanel";
import CoverPanel from "./CoverPanel";
import HomeSplitPanelControl from "./ui/HomeSplitPanelControl";
import GridPattern from "./ui/GridPattern";

export default function HomeSection({
  studies,
  itemPosition,
  itemHeight,
  studiesNumber,
  handleSplitPanelControlClick,
  panelScrollIndex,
  height,
}) {
  return (
    <section className="flex w-screen h-[calc(100vh-110px)] ">
      <HomeSplitPanelControl
        studiesNumber={studiesNumber}
        panelScrollIndex={panelScrollIndex}
        itemPosition={itemPosition}
        height={height}
        handleSplitPanelControlClick={handleSplitPanelControlClick}
      />

      <div className="w-1/2 ">
        <div
          className={`bg-panel1 bg-left background-size-full font-sans flex items-center flex-col h-[calc(100vh-110px)]`}
        >
          <GridPattern color={"deep-blue"} />
          <div className="absolute h-1/2 flex flex-col justify-center p-[5vmax]">
            <h1 className="uppercase text-white text-[4vmax] ">Insight AM</h1>
            <div className="w-[3vmax] h-[0.5vmax] bg-pink mb-[2vmax] mt-[0.5vmax]"></div>
            <p className="font-serif text-white text-[2vmax] leading-normal tracking-wider  ">
              Études de marché et stratégies marketing&nbsp;
              <span className="text-pink">
                pour les producteurs et intermédiaires en produits financiers.
              </span>
            </p>
          </div>
        </div>

        {/* LOOP ON STUDIES */}
        {studies.data.map((study, index) => (
          <ContentPanel
            itemHeight={itemHeight}
            key={index + "content"}
            heading={study.attributes.heading}
            theme={study.attributes.theme}
            title={study.attributes.title}
            description={study.attributes.description}
            index={study.id}
            primaryButtonLabel={study.attributes.primaryButtonLabel}
            secondaryButtonLabel={study.attributes.secondaryButtonLabel}
            itemsCount={studies.data.length}
            itemPosition={itemPosition}
            slug={study.attributes.slug}
          />
        ))}
      </div>
      <div className="w-1/2">
        <div
          className={`bg-panel1 bg-right background-size-full flex flex-col justify-end bg-deep-blue flex h-[calc(100vh-110px)]`}
        >
          {/* <GridPattern color={"deep-blue"} /> */}

          <div className="absolute bg-deep-blue bg-opacity-85 h-[calc(50%-46px)] flex flex-col justify-center pr-[7vmax] pl-[7vmax]">
            <h2 className="text-white font-serif text-[1.2vmax] mb-[1vmax]">
              Nos objectifs
            </h2>

            <ul className="text-white font-serif text-[1vmax] list-disc mb-[2vmax] ml-[17px] leading-[2vmax]">
              <li>
                Accompagner les acteurs du marché dans la compréhension des
                attentes des investisseurs et distributeurs,
              </li>
              <li>
                Identifier les tendances et capter les signaux faibles de la
                tiers distribution,
              </li>
              <li>
                Revisiter le positionnement des gammes de produits à destination
                des épargnants,
              </li>
              <li>
                Valider les choix des producteurs et distributeurs dans le
                lancement de nouveaux produits.
              </li>
            </ul>
          </div>
        </div>

        {/* LOOP ON STUDIES */}
        {studies.data
          .slice(0)
          .reverse()
          .map((study, index) => (
            <CoverPanel
              itemHeight={itemHeight}
              key={index + "cover"}
              index={study.id}
              itemsCount={studies.data.length}
              cover={study.attributes.cover.data.attributes.formats.large.url}
              itemPosition={itemPosition}
            />
          ))}
      </div>
    </section>
  );
}

CoverPanel.js

import { motion, transform } from "framer-motion";

import GridPattern from "./ui/GridPattern";

export default function CoverPanel({
  index,
  itemsCount,
  cover,
  itemPosition,
  itemHeight,
}) {
  return (
    <div className="w-screen h-[calc(100vh-110px)]">
      <div
        className={`flex flex-row h-[calc(100vh-110px)] translate-y-[calc(-500vh+550px)]`}
      >
        {/* COVER PANEL */}
        <motion.div
          className={`bg-bottom flex w-1/2 items-center justify-center `}
          animate={{ y: -itemPosition }}
          transition={{ ease: "anticipate", duration: 1 }}
        >
          <GridPattern color={"deep-blue"} cover={cover} />
        </motion.div>
      </div>
    </div>
  );
}

ContentPanel.js

import { motion, transform } from "framer-motion";
import useDeviceSize from "../components/hooks/useDevicesize";

import Button from "./ui/Button";
import GridPattern from "./ui/GridPattern";

import { themeBeautyfier } from "../utils/themeBeautyfier";

export default function ContentPanel({
  heading,
  theme,
  title,
  description,
  primaryButtonLabel,
  secondaryButtonLabel,
  index,
  itemPosition,
  slug,
}) {
  const [width, height] = useDeviceSize();

  return (
    <div className="w-screen h-[calc(100vh-110px)] w-screen">
      <div className={`flex flex-row h-[calc(100vh-110px)]`}>
        {/* CONTENTPANEL     */}
        <motion.div
          className={`bg-beige w-1/2 font-sans flex items-center flex-col justify-center`}
          initial={false}
          animate={{ y: itemPosition }}
          transition={{ ease: "anticipate", duration: 1 }}
        >
          <GridPattern color={"white"} />
          <div className="z-20 pr-[7vmax] pl-[7vmax]">
            <div className="z-20">
              <p className="text-deep-blue font-sans text-[1.2vmax] mb-[1vmax] uppercase">
                {heading}
              </p>

              <p className="uppercase text-pink text-[0.7vmax]">
                {themeBeautyfier(theme)}
              </p>
              <div className="w-[2.5vmax] h-[0.4vmax] bg-pink mb-[2vmax] mt-[0.5vmax]"></div>
              <h2 className="text-deep-blue font-serif text-[3vmax] mb-[1vmax] leading-[3.7vmax]  ">
                {title}
              </h2>
              <p className="font-serif text-[1vmax] text-black mb-[1vmax]">
                {description}
              </p>
              <div className="mb-[3vmax]">
                <a className="font-serif text-[0.9vmax] underline mt-[2vmax] mb-[2vmax]">
                  Mon lien vers un site
                </a>
              </div>
              <div>
                {primaryButtonLabel && (
                  <Button
                    label={primaryButtonLabel}
                    type={"primary"}
                    index={index}
                    slug={slug}
                  />
                )}

                {secondaryButtonLabel && (
                  <Button
                    label={secondaryButtonLabel}
                    type={"secondary"}
                    style={"light"}
                  />
                )}
              </div>
            </div>
          </div>
        </motion.div>
        {/* CONTENTPANEL     */}
      </div>
    </div>
  );
}

最后,我的文件结构:

【问题讨论】:

标签: node.js deployment next.js netlify


【解决方案1】:

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
猜你喜欢
  • 2021-05-31
  • 1970-01-01
  • 2020-08-15
  • 2022-11-11
  • 2020-10-04
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多