nx/docs/shared/recipes/add-stack/add-solid.md
2023-08-02 15:37:51 +01:00

8.0 KiB

Add a New Solid Project

The code for this example is available on GitHub:

{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/solidjs" %}

Supported Features

Because we are not using an Nx plugin for Solid, there are few items we'll have to configure manually. We'll have to configure our own build system. There are no pre-created Solid-specific code generators. And we'll have to take care of updating any framework dependencies as needed.

{% pill url="/core-features/run-tasks" %} Run Tasks{% /pill %} {% pill url="/core-features/cache-task-results" %} Cache Task Results{% /pill %} {% pill url="/core-features/remote-cache" %} Share Your Cache{% /pill %} {% pill url="/core-features/explore-graph" %} Explore the Graph{% /pill %} {% pill url="/core-features/distribute-task-execution" %} Distribute Task Execution{% /pill %} {% pill url="/core-features/integrate-with-editors" %} Integrate with Editors{% /pill %} {% pill url="/core-features/automate-updating-dependencies" %} Automate Updating Nx{% /pill %} {% pill url="/core-features/enforce-module-boundaries" %} Enforce Module Boundaries{% /pill %} {% pill url="/core-features/plugin-features/use-task-executors" %}🚫 Use Task Executors{% /pill %} {% pill url="/core-features/plugin-features/use-code-generators" %}🚫 Use Code Generators{% /pill %} {% pill url="/core-features/automate-updating-dependencies" %}🚫 Automate Updating Framework Dependencies{% /pill %}

Install Solid and Other Dependencies

{% tabs %} {% tab label="npm" %}

npm i solid-js
npm i --save-dev @nx/web solid-devtools vite-plugin-solid

{% /tab %} {% tab label="yarn" %}

yarn add solid-js
yarn add --dev @nx/web solid-devtools vite-plugin-solid

{% /tab %} {% tab label="pnpm" %}

pnpm i solid-js
pnpm i --save-dev @nx/web solid-devtools vite-plugin-solid

{% /tab %} {% /tabs %}

Create an Application

We'll start with a web application and then tweak the settings to match what we need. Add a new web application to your workspace with the following command:

nx g @nx/web:app my-solid-app --bundler=vite

The @nx/web:app generator will create some files that are unnecessary for our Solid application.

The files to be deleted are:

  • apps/my-solid-app/src/public
  • apps/my-solid-app/src/app
  • apps/my-solid-app/main.ts
  • apps/my-solid-app/styles.css
  • apps/my-solid-app/.babelrc

Turn the Application into a Solid Application

Now we'll create the files that are necessary to turn our application into a Solid application.

Add the following files

import type { Component } from 'solid-js';

const App: Component = () => {
  return (
    <div>
      <header>
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          href="https://github.com/solidjs/solid"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn Solid Now
        </a>
      </header>
    </div>
  );
};

export default App;
/* @refresh reload */
import { render } from 'solid-js/web';

import App from './App';

const root = document.getElementById('root');

if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
  throw new Error(
    'Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?'
  );
}

render(() => <App />, root!);

Update the following files

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <title>Solid App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>

    <script src="src/index.tsx" type="module"></script>
  </body>
</html>
/// <reference types="vitest" />
import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';
// import devtools from 'solid-devtools/vite';

import viteTsConfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
  cacheDir: '../../node_modules/.vite/my-solid-app',

  server: {
    port: 3000,
  },

  build: {
    target: 'esnext',
  },

  plugins: [
    viteTsConfigPaths({
      root: '../../',
    }),
    /*
                                                                        Uncomment the following line to enable solid-devtools.
                                                                        For more info see https://github.com/thetarnav/solid-devtools/tree/main/packages/extension#readme
                                                                        */
    // devtools(),
    solidPlugin(),
  ],

  // Uncomment this if you are using workers.
  // worker: {
  //  plugins: [
  //    viteTsConfigPaths({
  //      root: '../../',
  //    }),
  //  ],
  // },

  test: {
    globals: true,
    cache: {
      dir: '../../node_modules/.vitest',
    },
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
  },
});
{
  "extends": "../../tsconfig.base.json",
  "files": [],
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ESNext", "DOM"],
    "moduleResolution": "Node",
    "jsx": "preserve",
    "jsxImportSource": "solid-js",
    "strict": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "noEmit": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "skipLibCheck": true,
    "types": ["vite/client", "vitest"]
  },
  "include": ["src"],
  "references": [
    {
      "path": "./tsconfig.app.json"
    },
    {
      "path": "./tsconfig.spec.json"
    }
  ]
}

You can now run nx serve my-solid-app and your Solid application can be viewed in your browser!

Create a Library

Let's create a library that our Solid application is going to consume. To create a new library, install the @nx/js package and run:

nx g @nx/js:lib my-lib

Once the library is created, update the following files.

Rename libs/my-lib/src/lib/my-lib.ts -> libs/my-lib/src/lib/my-lib.tsx, then edit the contents to:

export function MyLibComponent(props: { name: string }) {
  return <h1>Hello {props.name} from MyLib</h1>;
}
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "module": "commonjs",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "jsx": "preserve",
    "jsxImportSource": "solid-js",
    "types": ["vitest"]
  },
  "files": [],
  "include": [],
  "references": [
    {
      "path": "./tsconfig.lib.json"
    },
    {
      "path": "./tsconfig.spec.json"
    }
  ]
}
import type { Component } from 'solid-js';
import { MyLibComponent } from '@acme/my-lib';

const App: Component = () => {
  return (
    <div>
      <header>
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <MyLibComponent name={'there'} />
        <a
          href="https://github.com/solidjs/solid"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn Solid Now
        </a>
      </header>
    </div>
  );
};

export default App;

Now when you serve your application, you'll see the content from the library being displayed.

More Documentation