Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update realtime SPA docs #2025

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Nathan-8963
Copy link

This updates some outdated documentation. Loading the JS SDK is still outdated since ihp-datasync.js was moved outside of vendor/, see af883a4. This raises the question: how should ihp-datasync.js and ihp-querybuilder.js be loaded in the frontend?

@Nathan-8963 Nathan-8963 force-pushed the update-realtime-spa-docs branch from b6b4b40 to d0d3cd0 Compare December 30, 2024 01:47
@mpscholten
Copy link
Member

Thanks for updating this 👍

The undocumented best practise for development is to set up bundling with devenv. Here is a snippet copied from a local project:

                # Custom configuration that will start with `devenv up`
                devenv.shells.default = {
                    process.implementation = "overmind";

                    # Custom processes that don't appear in https://devenv.sh/reference/options/
                    processes.frontend.exec =
                        let
                            ihpNodeModules = pkgs.runCommand "ihp-node-modules" {} ''
                                mkdir -p $out
                                ln -s ${ihp}/lib/IHP/DataSync $out/ihp-datasync
                                # ln -s /Users/marc/digitallyinduced/ihp/lib/IHP/DataSync $out/ihp-datasync
                            '';
                        in
                            ''
                                mkdir -p static/Frontend

                                touch Frontend/src/index.tsx # Force rebuild

                                cd Frontend
                                NODE_PATH=${ihpNodeModules}:node_modules ${pkgs.esbuild}/bin/esbuild src/index.tsx \
                                    --bundle \
                                    --preserve-symlinks \
                                    --loader:.woff=file \
                                    --loader:.woff2=file \
                                    --loader:.ttf=file \
                                    --loader:.svg=file \
                                    --loader:.png=file \
                                    --loader:.gif=file \
                                    --main-fields=module,main \
                                    --define:global=globalThis \
                                    --outfile=../static/Frontend/main.js \
                                    --watch=forever
                            '';

The ihp-datasync module is now loaded by injecting it into NODE_PATH. And then bundling it together with esbuild.

Esbuild bundles the Frontend/src/index.tsx file. This needs a bit of adjustments for the docs as they're not using typescript (it would be good to update the docs to use typescript actually).

Also instead of npm we need to use yarn, because nix has better yarn support.

Other useful nix snippets:

# Add a script to generate typescript definitions
                    scripts.update-typescript-types.exec = ''
                        ${ihp.packages.${system}.datasync-typescript}/bin/generate-datasync-types Application/Schema.sql Frontend/types/ihp-datasync/index.d.ts
                    '';

# Add DataSync to the NODE_PATH
                    env.NODE_PATH =
                        let
                            ihpNodeModules = pkgs.runCommand "ihp-node-modules" {} ''
                                mkdir -p $out
                                ln -s ${ihp}/lib/IHP/DataSync $out/ihp-datasync
                            '';
                        in
                            "${ihpNodeModules}:node_modules"
                        ;

For production builds the following nix snippets are useful:

                packages.frontend =
                    let
                        node-modules = pkgs.mkYarnModules {
                            pname = "${config.ihp.appName}-frontend-deps";
                            packageJSON = ./Frontend/package.json;
                            yarnLock = ./Frontend/yarn.lock;
                            version = "1.0.0";
                        };
                        filter = ihp.inputs.nix-filter.lib;
                    in pkgs.stdenv.mkDerivation {
                        name = "${config.ihp.appName}-frontend";
                        src = filter {
                            root = ./Frontend;
                            include = ["src" "types" (filter.matchExt "js") (filter.matchExt "ts") (filter.matchExt "tsx") (filter.matchExt "json") (filter.matchExt "css")];
                            exclude = ["node_modules"];
                        };
                        nativeBuildInputs = [pkgs.yarn node-modules pkgs.esbuild];
                        allowedReferences = [];
                        buildPhase = ''
                            mkdir -p ihp-node_modules
                            ln -s ${ihp}/lib/IHP/DataSync ihp-node_modules/ihp-datasync

                            NODE_PATH=ihp-node_modules:${node-modules}/node_modules \
                            ${node-modules}/node_modules/.bin/tailwindcss -i ./src/globals.css -o ./src/tailwind.css

                            NODE_PATH=ihp-node_modules:${node-modules}/node_modules \
                            ${pkgs.esbuild}/bin/esbuild src/index.tsx \
                                --bundle \
                                --preserve-symlinks \
                                --loader:.woff=file \
                                --loader:.woff2=file \
                                --loader:.ttf=file \
                                --loader:.svg=file \
                                --loader:.png=file \
                                --loader:.gif=file \
                                --main-fields=module,main \
                                --define:global=globalThis \
                                --define:process.env.NODE_ENV=\"production\" \
                                --minify \
                                --legal-comments=none \
                                --outfile=$out/main.js \
                        '';
                    };

                packages.optimized-prod-server-with-frontend = self.packages."${system}".optimized-prod-server.overrideAttrs (finalAttrs: previousAttrs: {
                        name = "${previousAttrs.name}-with-frontend";
                        nativeBuildInputs = previousAttrs.nativeBuildInputs ++ [ self.packages."${system}".frontend ];
                        preBuild = ''
                            mkdir -p static/Frontend
                            ln -s ${self.packages."${system}".frontend}/main.js static/Frontend/main.js
                            ln -s ${self.packages."${system}".frontend}/main.css static/Frontend/main.css
                        '';
                    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants