nathanjhood / ts-esbuild-react

A React starter project template, powered by esbuild's Typescript support, with hot-reloading dev server.
https://nh-pages.stoneydsp.com/ts-esbuild-react/
Other
0 stars 0 forks source link

Development/plugins #15

Closed nathanjhood closed 4 weeks ago

nathanjhood commented 4 weeks ago

I need an InterpolateHtmlPlugin for esbuild...

The is the Webpack plugin definition, written in CommonJS, that ships with react-scripts, which handles the var replacements (%PUBLIC_URL%) inside the public/index.html file of a standard React/Webpack project:

const escapeStringRegexp = require('escape-string-regexp');

class InterpolateHtmlPlugin {
  constructor(htmlWebpackPlugin, replacements) {
    this.htmlWebpackPlugin = htmlWebpackPlugin;
    this.replacements = replacements;
  }

  apply(compiler) {
    compiler.hooks.compilation.tap('InterpolateHtmlPlugin', compilation => {
      this.htmlWebpackPlugin
        .getHooks(compilation)
        .afterTemplateExecution.tap('InterpolateHtmlPlugin', data => {
          // Run HTML through a series of user-specified string replacements.
          Object.keys(this.replacements).forEach(key => {
            const value = this.replacements[key];
            data.html = data.html.replace(
              new RegExp('%' + escapeStringRegexp(key) + '%', 'g'),
              value
            );
          });
        });
    });
  }
}

I need to adapt this to an esbuild plugin, written in Typescript to be transpiled to JS for distro.

Sure enough we can do a slow fs.read/fs.write of some sort, and even mark it as async. I'm wondering - influenced by an idea from expo - if perhaps the HTML file could be parsed as JSX, and then the transformation can be done in some sort of JS function on the interpreted JSX version of the HTML file...

The parsed JSX version of the HTML would look something like:

import * as React from "react";
import * as ReactDOM from "react-dom";

export const Index = () => {
  return (
    <html lang="en">
      <head>
      <meta charset="utf-8" />
      <link rel="icon" href="./favicon.ico" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta name="theme-color" content="#000000" />
      <meta name="description" content="Web site created using ts-esbuild-react" />
      <link rel="apple-touch-icon" href="./logo192.png" />
      {
        /**
         * manifest.json provides metadata used when your web app is installed
         * on a user's mobile device or desktop.
         * See https://developers.google.com/web/fundamentals/web-app-manifest/
         */
      }
      <link rel="manifest" href={ process.env.PUBLIC_URL + "manifest.json" } />
      {
        /**
         * Notice the use of %PUBLIC_URL% in the tags above.
         * It will be replaced with the URL of the `public` folder during the build.
         * Only files inside the `public` folder can be referenced from the HTML.
         *
         * Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
         * work correctly both with client-side routing and a non-root public URL.
         * Learn how to configure a non-root public URL by running `npm run build`.
         */
      }
      <meta name="referrer" content="no-referrer" />
      <link rel="stylesheet" href={ process.env.PUBLIC_URL + "index.jcss" } />
      <title>React App</title>
    </head>
    <body>
      <noscript>
        We're sorry but this application doesn't work properly without Javascript
        enabled. Please enable it to continue.
      </noscript>
      <div id="root"></div>
        {
          /**
           * This HTML file is a template.
           * If you open it directly in the browser, you will see an empty page.
           *
           * You can add webfonts, meta tags, or analytics to this file.
           * The build step will place the bundled scripts into the <body> tag.
           *
           * To begin the development, run `npm start` or `yarn start`.
           * To create a production bundle, use `npm run build` or `yarn build`.
           */
        }

      <script type="module" src={ process.env.PUBLIC_URL + "index.js" }></script>
    </body>
  </html>
  )
}

export default Index;
vercel[bot] commented 4 weeks ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
ts-esbuild-react ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 19, 2024 7:39pm