denoland / fresh

The next-gen web framework.
https://fresh.deno.dev
MIT License
12.23k stars 623 forks source link

Islands not working but only in some environments #2659

Open diegojromerolopez opened 5 days ago

diegojromerolopez commented 5 days ago

Hello Fresh maintainers.

I have a bug in a project: the islands do not work. But this only happens in the production environment.

The island

The island in question (it moves a space ship left and right constantly):

import { useEffect } from "preact/hooks";

export function SpaceShip() {
  useEffect(() => {
    const ship = document.getElementById("ship");
    if (ship) {
      const pageWidth = ship.parentElement?.offsetWidth || 100;
      let direction: "left" | "right" = "right";
      let offset = 0;
      setInterval(function () {
        if (offset > pageWidth) {
          direction = "left";
        } else if (offset < 0) {
          direction = "right";
        }

        switch (direction) {
          case "left":
            ship.style.marginLeft = offset-- + "px";
            ship.className = "scale-x-[-1]";
            break;

          case "right":
            ship.style.marginLeft = offset++ + "px";
            ship.className = "";
            break;
        }
      }, 45);
    }
  }, []);

  return (
    <img
      id="ship"
      src="/ship.png"
    />
  );
}

As you see, the code does not even need to store some state nor anything.

The problem

When running the island in development deno run -A --watch=static/,routes/ dev.ts it works.

When using a Dockerfile and running it seems to work.

FROM denoland/deno:1.46.2
WORKDIR /app
RUN apt-get update && apt-get upgrade -y
COPY . .
RUN deno cache main.ts
RUN deno task build
ENTRYPOINT ["deno", "run", "-A", "/app/main.ts"]

But when deploying that docker image it doesn't. I get no errors, nothing from the console.

I would not bother you but while the islands are loaded, they do not run and I'm out of options here.

Thank you.

marvinhagemeister commented 4 days ago

I'm not able to reproduce that. I've created a new Fresh project, added the island you shared and built the docker image. When running the docker image I see the ship moving as expected.

https://github.com/marvinhagemeister/fresh-ship-demo

https://github.com/user-attachments/assets/619a5aab-b040-4696-bd35-bcc592557dee

diegojromerolopez commented 4 days ago

Thank you for taking the time to respond and doing it so fast. I really appreciate it.

So, it should be caused by some weird configuration in my production then.

Does the islands need some kind of network connection at first to be triggered? (please bear in mind I have no frontend background).

EDIT: if you could orient me a bit on the steps to debug this issue, is there any guide for that? Thanks!

marvinhagemeister commented 4 days ago

Does the islands need some kind of network connection at first to be triggered? (please bear in mind I have no frontend background).

No, the deno task build takes care of preparing the islands in its final form. There are no further network requests required. Are the islands at least rendering as in the ship being there but just not moving?

diegojromerolopez commented 4 days ago

Exactly the ship appears but does not move.

Maybe it could be that in the process of compiling the resources I have some bugs in the HTML and that breaks all islands?

marvinhagemeister commented 4 days ago

Do you see any script tags in the HTML in the browser?

diegojromerolopez commented 4 days ago

Yes I have the following script tags in the page that shows the ship:

<script id="__FRSH_STATE_fb8125c3-e6ce-4213-ad01-85b2660b8056" type="application/json" nonce="3601c039606b4270a28971656b2c1597">{"v":[[{}],[]]}</script>

<script type="module" nonce="3601c039606b4270a28971656b2c1597">const ST = document.getElementById("__FRSH_STATE_fb8125c3-e6ce-4213-ad01-85b2660b8056").textContent;const STATE = JSON.parse(ST).v;import { revive } from "/_frsh/js/20bb641b4bae534a0b2f6e159f26b3fc8deeac65/main.js";import { ShipSailing as shipsailing_ShipSailing } from "/_frsh/js/20bb641b4bae534a0b2f6e159f26b3fc8deeac65/island-shipsailing.js";const propsArr = typeof STATE !== "undefined" ? STATE[0] : [];revive({shipsailing_shipsailing:shipsailing_ShipSailing,}, propsArr);</script><

Note that in my code the island is named SpaceShip, I mistyped it earlier by mistake (didn't remember what I wrote).

No error on the console either 😞

marvinhagemeister commented 4 days ago

Looks like only island-shipsailing.js is registered as an island. What's the project path to your SpaceShip island file? Is it located inside the islands/ folder?

diegojromerolopez commented 4 days ago

Yes it is placed inside the islands folder. The worst of this is that it works with the dev server.

marvinhagemeister commented 4 days ago

What's the output when building the docker container. Are there any hints that something went wrong?

diegojromerolopez commented 4 days ago

Well nothing out of the ordinary in the docker, as far as I know.

I'm using the following import deno.ts:

{
  "lock": false,
  "tasks": {
    "check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx",
    "cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -",
    "manifest": "deno task cli manifest $(pwd)",
    "start": "deno run -A --watch=static/,routes/ dev.ts",
    "build": "deno run -A dev.ts build",
    "preview": "deno run -A main.ts",
    "update": "deno run -A -r https://fresh.deno.dev/update .",
    "tests": "deno test --allow-env **/*_test.ts",
  },
  "lint": { "rules": { "tags": ["fresh", "recommended"] } },
  "exclude": ["**/_fresh/*"],
  "imports": {
    "@/": "./",
    "$fresh/": "https://deno.land/x/fresh@1.6.8/",
    "$fresh-testing-library": "https://deno.land/x/fresh_testing_library@0.13.0/mod.ts",
    "$fresh-testing-library/": "https://deno.land/x/fresh_testing_library@0.13.0/",
    "preact": "https://esm.sh/preact@10.19.6",
    "preact/": "https://esm.sh/preact@10.19.6/",
    "preact-render-to-string": "https://esm.sh/*preact-render-to-string@6.1.0",
    "@preact/signals": "https://esm.sh/*@preact/signals@1.2.2",
    "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.1",
    "tailwindcss": "npm:tailwindcss@3.4.1",
    "tailwindcss/": "npm:/tailwindcss@3.4.1/",
    "tailwindcss/plugin": "npm:/tailwindcss@3.4.1/plugin.js",
    "$std/": "https://deno.land/std@0.216.0/",
  },
  "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact" },
  "nodeModulesDir": true
}

but if there was there an issue, that should also affect the development server, right?

marvinhagemeister commented 3 days ago

but if there was there an issue, that should also affect the development server, right?

Yeah that's what's a bit baffling to me. Do you see the island file in the fresh.gen.ts file inside the docker container?

diegojromerolopez commented 3 days ago

Yes it is there:

// DO NOT EDIT. This file is generated by Fresh.
// This file SHOULD be checked into source version control.
// This file is automatically updated during development when running `dev.ts`.

import * as $_404 from "./routes/_404.tsx";
import * as $_app from "./routes/_app.tsx";
import * as $_middleware from "./routes/_middleware.ts";
import * as $about from "./routes/about.tsx";
import * as $index from "./routes/index.tsx";
import * as $ShipSailing from "./islands/ShipSailing.tsx";
import { type Manifest } from "$fresh/server.ts";

const manifest = {
  routes: {
    "./routes/_404.tsx": $_404,
    "./routes/_app.tsx": $_app,
    "./routes/_middleware.ts": $_middleware,
    "./routes/about.tsx": $about,
    "./routes/index.tsx": $index,
},
  islands: {
    "./islands/ShipSailing.tsx": $ShipSailing,
  },
  baseUrl: import.meta.url,
} satisfies Manifest;

export default manifest;

No worries. I don't want to waste more of your time.

Locally, the same docker image works fine. So it needs to be an issue with some configuration that only applies in the cloud. I will continue investigating and if I find what is happening will post it here.

Thank you for your effort!

marvinhagemeister commented 3 days ago

If locally the docker image works fine, then the problem is with the cloud. It sounds like your new image isn't getting deployed or the deployment is still using the old one.

diegojromerolopez commented 1 day ago

Yes, the docker image seems to be fine as it contains the last updates and it is the same deployed in pre-production (and islands work there fine).

I will investigate and once I have a solution will update here.

Thank you!