ryansolid / solid-ssr-workbench

17 stars 3 forks source link

Use TypeScript in code files in shared/src/ #2

Open zejji opened 3 years ago

zejji commented 3 years ago

For the same reasons noted in this discussion - principally maintainability once a project becomes larger than a toy example - it would be helpful to convert this repository to use TypeScript.

I have attempted to do the conversion myself, by adding the @rollup/plugin-typescript plugin and using a tsconfig.json file based on the Create Solid TypeScript starter, but have been unable to get the build to complete despite spending numerous hours tweaking the rollup and tsconfig options.

Specifically, I get one of two errors.

If the acorn-jsx plugin is enabled as described here, I get the following error:

src/index.tsx → dist/public/js...
  564 | 
  565 | // entry point for browser
> 566 | hydrate(() => <App />, document.getElementById("app"));
      |              ^ Unexpected token: operator (<)
[!] (plugin terser) SyntaxError: Unexpected token: operator (<)
SyntaxError: Unexpected token: operator (<)

If the acorn-jsx plugin is not enabled, I get the following error (one which spawned a very long, and unresolved, GitHub issue here):

src/index.tsx → dist/public/js...
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src\index.tsx (4:14)
2: import App from "./App";
3: // entry point for browser
4: hydrate(() => <App />, document.getElementById("app"));

If anyone happens to have a working SSR/TypeScript configuration, I think it would be very helpful to include it in the repo! 😃

I'm conscious that a Solid starter kit is in the works, which is likely to include both SSR and TypeScript support, but adding a basic example of TypeScript support to this repo would make it possible to continue working on an SSR/TypeScript Solid solution at the present time, pending completion of that project. This would serve to unblock current development and facilitate porting over later.

ryansolid commented 3 years ago

I see the desire but this repo is just where I am trying ideas. There is still a lot of experimental stuff I'm going to be working on, including streaming HTML, partial hydration etc... It's a place for me to work. I pulled it out of the main repo as I wanted a place to try stuff without messing with things there. I can probably look at updating the examples in solid-ssr. Although it sounds more like you'd be looking for a simple starter template.

As for the issues you hit. In general, using Babel Preset TypeScript and avoiding the TS compiler except for type checking is infinitely simpler.

zejji commented 3 years ago

@ryansolid - Thanks, I will give that a try with Babel Preset TypeScript. 😃

As you say, a starter template will be much appreciated once it's ready, but I know it's a huge amount of work to finalize and likely a while off. The main thing I'm trying to achieve at the moment is to start productive work - I'm very happy to port over the code to the starter template later - but at an absolute minimum I know the solution will need to work with both SSR and TypeScript (and ideally Tailwind also). Hot reload and other developer niceties are not essential at this stage. 😉

However, I'm a little wary of trying to start with the current Create Solid template and to retrofit SSR/TS later once a significant amount of work has been done, as I suspect that will be trickier.

ryansolid commented 3 years ago

I'd start with Vite then..maybe something like: https://github.com/amoutonbrady/vite-ssr-solid. I can't remember if that one was in working condition. This is probably worth a look too: https://github.com/amoutonbrady/solid-hackernews

zejji commented 3 years ago

@ryansolid - Thanks, I will check those repos out

zejji commented 3 years ago

Just to note that I finally got the project to build successfully using TypeScript. The key was ensuring that the TypeScript was correctly processed by the node-resolve and babel plugins. This required the appropriate TypeScript file extensions (.ts and .tsx) to be added to the extensions plugin option (see this issue for details).

My final rollup.config.js file was as follows:

import path from "path";
import { DEFAULTS, nodeResolve } from "@rollup/plugin-node-resolve";
import babel from "@rollup/plugin-babel";
import json from "@rollup/plugin-json";
import copy from "rollup-plugin-copy";
import { terser } from "rollup-plugin-terser";
import manifest from "rollup-route-manifest";
import typescript from "@rollup/plugin-typescript";
import { DEFAULT_EXTENSIONS } from '@babel/core';

const typescriptExtensions = [
  '.ts',
  '.tsx'
];

const nodeResolveExtensions = [
  ...(DEFAULTS.extensions),
  ...typescriptExtensions
];

const babelExtensions = [
  ...DEFAULT_EXTENSIONS,
  ...typescriptExtensions
];

export default [
  {
    input: "src/index.tsx",
    output: [
      {
        dir: "dist/public/js",
        format: "esm",
      }
    ],
    preserveEntrySignatures: false,
    plugins: [
      nodeResolve({
        extensions: nodeResolveExtensions,
        exportConditions: ["solid"]
      }),
      typescript(),
      babel({
        extensions: babelExtensions,
        babelHelpers: "bundled",
        presets: [["solid", { generate: "dom", hydratable: true }]]
      }),
      copy({
        targets: [
          {
            src: ["static/*"],
            dest: "dist/public"
          }
        ]
      }),
      manifest({
        inline: false,
        merge: false,
        publicPath: "/js/",
        routes: file => {
          file = file.replace(path.join(__dirname, "src"), "").replace(/\.[tj]sx?$/, "");
          if (!file.includes("/pages/")) return "*"; // commons
          let name = "/" + file.replace("/pages/", "").toLowerCase();
          return name === "/home" ? "/" : name;
        }
      }),
      terser()
    ]
  },
  {
    input: "index.js",
    output: [
      {
        dir: "dist/lib",
        format: "cjs",
      }
    ],
    external: [
      "solid-js",
      "solid-js/web",
      "path",
      "express",
      "stream",
      "compression",
      "node-fetch"
    ],
    plugins: [
      nodeResolve({
        extensions: nodeResolveExtensions,
        preferBuiltins: true,
        exportConditions: ["solid"]
      }),
      typescript(),
      babel({
        extensions: babelExtensions,
        babelHelpers: "bundled",
        presets: [["solid", { generate: "ssr", hydratable: true }]]
      }),
      json()
    ],
    preserveEntrySignatures: false
  }
];
aadamsx commented 3 years ago

@zejji do you have a repo with the rest of the files/npm modules needed to get typescript working here?

lighth7015 commented 7 months ago

I would love to see that as well!