Skip to content

Commit

Permalink
experimental: support image processing in docker template (#4762)
Browse files Browse the repository at this point in the history
Added image a route for image processing in docker template based on ipx
package.

There a few things to note
- it does not have persistent caching and rely only on client cache
control
- performance is not good for remote images
- the package adds 30MB to node_modules, though it will be fixed soon

There is a DOMAINS env variable with comma-separated hosts to restrict
remote images processing similar to netlify and vercel.

Can be tested only locally for now.
  • Loading branch information
TrySound authored Jan 20, 2025
1 parent bcf1eed commit 51ae04c
Show file tree
Hide file tree
Showing 10 changed files with 953 additions and 37 deletions.
1 change: 1 addition & 0 deletions fixtures/react-router-docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ COPY ./package.json package-lock.json /app/
COPY --from=production-dependencies-env /app/node_modules /app/node_modules
COPY --from=build-env /app/build /app/build
WORKDIR /app
# there is a DOMAINS env with comma separated allowed domains for image processing
CMD ["npm", "run", "start"]
10 changes: 8 additions & 2 deletions fixtures/react-router-docker/app/constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ export const imageBaseUrl = "/assets/";
/**
* @type {import("@webstudio-is/image").ImageLoader}
*/
export const imageLoader = ({ src }) => {
return src;
export const imageLoader = (props) => {
if (props.format === "raw") {
return props.src;
}
// handle absolute urls
const path = URL.canParse(props.src) ? `/${props.src}` : props.src;
// https://github.com/unjs/ipx?tab=readme-ov-file#modifiers
return `/_image/w_${props.width},q_${props.quality}${path}`;
};
24 changes: 24 additions & 0 deletions fixtures/react-router-docker/app/routes/[_image].$.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { env } from "node:process";
import type { LoaderFunctionArgs } from "react-router";
import {
createIPX,
createIPXH3Handler,
ipxFSStorage,
ipxHttpStorage,
} from "ipx";
import { createApp, toWebHandler } from "h3";

const domains = env.DOMAINS?.split(/\s*,\s*/) ?? [];

const ipx = createIPX({
storage: ipxFSStorage({ dir: "./public" }),
httpStorage: ipxHttpStorage({ domains }),
});

const handleRequest = toWebHandler(
createApp().use("/_image", createIPXH3Handler(ipx))
);

export const loader = async (args: LoaderFunctionArgs) => {
return handleRequest(args.request);
};
2 changes: 2 additions & 0 deletions fixtures/react-router-docker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"@webstudio-is/sdk-components-react": "workspace:*",
"@webstudio-is/sdk-components-react-radix": "workspace:*",
"@webstudio-is/sdk-components-react-router": "workspace:*",
"h3": "^1.13.1",
"ipx": "^3.0.1",
"isbot": "^5.1.19",
"react": "18.3.0-canary-14898b6a9-20240318",
"react-dom": "18.3.0-canary-14898b6a9-20240318",
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
"@webstudio-is/sdk-components-react-remix": "workspace:*",
"@webstudio-is/sdk-components-react-router": "workspace:*",
"@webstudio-is/tsconfig": "workspace:*",
"h3": "^1.13.1",
"ipx": "^3.0.1",
"prettier": "3.4.2",
"react-dom": "18.3.0-canary-14898b6a9-20240318",
"react-router": "^7.1.1",
Expand Down
1 change: 1 addition & 0 deletions packages/cli/templates/react-router-docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ COPY ./package.json package-lock.json /app/
COPY --from=production-dependencies-env /app/node_modules /app/node_modules
COPY --from=build-env /app/build /app/build
WORKDIR /app
# there is a DOMAINS env with comma separated allowed domains for image processing
CMD ["npm", "run", "start"]
10 changes: 8 additions & 2 deletions packages/cli/templates/react-router-docker/app/constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ export const imageBaseUrl = "/assets/";
/**
* @type {import("@webstudio-is/image").ImageLoader}
*/
export const imageLoader = ({ src }) => {
return src;
export const imageLoader = (props) => {
if (props.format === "raw") {
return props.src;
}
// handle absolute urls
const path = URL.canParse(props.src) ? `/${props.src}` : props.src;
// https://github.com/unjs/ipx?tab=readme-ov-file#modifiers
return `/_image/w_${props.width},q_${props.quality}${path}`;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { env } from "node:process";
import type { LoaderFunctionArgs } from "react-router";
import {
createIPX,
createIPXH3Handler,
ipxFSStorage,
ipxHttpStorage,
} from "ipx";
import { createApp, toWebHandler } from "h3";

const domains = env.DOMAINS?.split(/\s*,\s*/) ?? [];

const ipx = createIPX({
storage: ipxFSStorage({ dir: "./public" }),
httpStorage: ipxHttpStorage({ domains }),
});

const handleRequest = toWebHandler(
createApp().use("/_image", createIPXH3Handler(ipx))
);

export const loader = async (args: LoaderFunctionArgs) => {
return handleRequest(args.request);
};
2 changes: 2 additions & 0 deletions packages/cli/templates/react-router-docker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"@webstudio-is/sdk-components-react-radix": "0.0.0-webstudio-version",
"@webstudio-is/sdk-components-react-router": "0.0.0-webstudio-version",
"@webstudio-is/sdk-components-react": "0.0.0-webstudio-version",
"h3": "^1.13.1",
"ipx": "^3.0.1",
"isbot": "^5.1.19",
"react": "18.3.0-canary-14898b6a9-20240318",
"react-dom": "18.3.0-canary-14898b6a9-20240318",
Expand Down
Loading

0 comments on commit 51ae04c

Please sign in to comment.