solidjs / solid

A declarative, efficient, and flexible JavaScript library for building user interfaces.
https://solidjs.com
MIT License
32.05k stars 914 forks source link

Reliability and Dependency Hell (Create Solid Development Setup) #144

Closed mudgen closed 3 years ago

mudgen commented 4 years ago

I just created a new solid project with: npm init solid app-ts my-app.

It worked perfectly. I started up the development server and all is nice. It looks great and I love it already.

But I noticed that creating the project added 1,805 npm packages to the project. So, in the future if one of these packages has an issue then my project might not work right?

I think this is probably the fault of the NodeJS ecosystem in general that has the convention to depend on hundreds or thousands of packages for projects. I just bring this to attention in case it is something that this project might want to mitigate in the future.

Or can someone tell me how this makes sense?

I do understand that the project that Solid sets up includes a lot of useful things like a testing library, development server, hot reload, babel, Typescript. But 1,805 dependencies still seems a lot to me. I know that it is similar for create-react-app.

ryansolid commented 4 years ago

The price you pay for using all the common DX libraries. This initial project is a fork of Create React App(https://github.com/facebook/create-react-app). They picked those packages to deliver what they felt was good DX experience for newcomers. I never use this for my own projects which are considerably smaller. I considered making my own starter but I doubt I would make something this comprehensive, atleast on my own.

I added this because it is familiar to people who have used CLI tools like this. It saved me from having to work through all the things someone might be look for. This is extensive considering a lot of concerns. I honestly don't even know how every part of it works it is that deep. Luckily React has good documentation.

mudgen commented 4 years ago

@ryansolid Thanks Ryan. What do you use for your own projects?

s0kil commented 4 years ago

It would be useful if Solid had a simple template starter similar to https://github.com/sveltejs/template.

ryansolid commented 4 years ago

Rollup but that is hardly the nicest DX. No dev-server. Less plugin support than Webpack. I feel like it isn't something I could just give to someone. I basically use whatever I feel like, but I also consider my self well versed. This is an area that a lot people find tricky. There are a number of starters people have made using Webpack as well (and even Parcel). If you are looking for a good TS starter this one was decent but a bit out of date: https://github.com/atfzl/solid-starter

I often scan through here. There are atleast half a dozen starters but I haven't had a chance to review them all: https://github.com/ryansolid/solid/network/dependents?package_id=UGFja2FnZS02MjAwMDg1Mg%3D%3D

mudgen commented 4 years ago

I understand. Thanks Ryan.

ryansolid commented 4 years ago

@s0kil I think that is Svelte's way around not having dedicated CLI. I don't mind that approach. But same stuff applies. It needs to be maintained and offer what people are looking for. I was hoping Create Solid handled that for us, but I guess it misaligns with peoples expectation of lightness.

mudgen commented 4 years ago

@ryansolid I appreciate Create Solid and I am using it for now. Thank you for setting it up! But I do like to keep dependencies to a minimum and I like to have some understanding about each dependency that I am using. In the future I probably will change my development setup.

@ryansolid It's possible that SolidJS might attract a different kind of developer than developers that stay with react.

ryansolid commented 4 years ago

Yeah I think so too on both accounts. I need to figure out how to better highlight community projects so that maybe it can naturally evolve to fit needs. I could just make a template on the main repo and people can start contributing but it needs guidance. We don't need me to set this up. It's a good task for someone else to do.

ryansolid commented 4 years ago

I agree in general so what way do people think we should take this:

1) Continue to work on a batteries included Create Solid Experience, work out options like Ejection. 2) a) Opt for a simpler "no config" with Parcel so modifying is on the end user. 2) b) Use a system like Rollup or Webpack with a simple config but you get what you get and there is no upgrade path.

high1 commented 4 years ago

I've converted most of my starter webpack react config to solid without much hassle. I had to use a local rule to make ESLint counts JSX as usage. One thing remains - tests. I was using testing-library - and I think that @testing-library/dom could be used. Is there a minimal sample which would create a valid dom output from a component somewhere in solid source, that could be used for testing components in isolation?

ryansolid commented 4 years ago

Yeah you bring up a good point. I've always just did simple testing winging it with Jest but a nicer higher level structured library would be great. Ok.. well simple DOM elements are simple.

Since well:

const el: HTMLDivElement = <div />

// so if:
const MyComp: Component = () => <div />

// then also:
const el2: HTMLDivElement = <MyComp />

It's a little bit trickier with fragments but still holds:

const frag: [HTMLDivElement, HTMLDivElement] = <><div /><div /></>

And this holds true for all Components that return those. But the problem is we can also return functions and fragments of functions for dynamic parts. The only thing that resolves them currently is the insert method, which is called inside render currently. Since dynamic insertion often requires the parent to insert into. So passing something to render and mounting in an arbitrary element (doesn't need to be connected to the DOM) is the only way to ensure DOM elements.

const container = document.createElement("div");
render(() => <MyComp />, container);
// our element/s will be found in container.childNodes

Although I'm not sure I understand your question in terms of minimal sample. The test folder under Solid JS should have some examples. In there it is a bit older where I do stuff like this as well but it's basically the same thing:

const container = createRoot(() =>
  <div>
    <MyComp /> 
  </div>
)

Does that help?

high1 commented 4 years ago

Here is the entry point to the application - it's minimal, but with all the boilerplate set up:

import { render, MountableElement } from 'solid-js/dom';

import Hello from 'components/Hello';

render(
  () => <Hello title="Welcome to Solid!" />,
  document.getElementById('root') as MountableElement
);

This works. image Then I tried to update the test I had for React.

import { render } from 'solid-js/dom';
import { getByText } from '@testing-library/dom';

test('renders without crashing', () => {
  const title = new Date().toTimeString();
  const renderMock = jest.fn((component, element) =>
    render(() => ({ ...component, props: { title } }), element)
  );
  jest.mock('solid-js/dom', () => ({
    render: renderMock,
  }));
  const root = document.createElement('div');
  root.setAttribute('id', 'root');
  document.body.appendChild(root);
  require('index');
  expect(renderMock).toHaveBeenCalledTimes(1);
  expect(getByText(root, 'root')).toHaveTextContent(title);
});

but this fails with:

dom_1.render(() => , document.getElementById('root')); ^

SyntaxError: Unexpected token '<'
ryansolid commented 4 years ago

Not compiling the JSX? Can see the CJS transpilation there though. At that point it should have compiled with Babel I think. Is this a Jest/Babel Config thing?

high1 commented 4 years ago

Yep, could be.

Jest encountered an unexpected token

This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

Here is .babelrc

{
  "presets": [
    "solid",
    "@babel/typescript",
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry"
      }
    ]
  ]
}

I'll have to check out ts-jest documentation about this... My bad, ts-jest does not use Babel by default. Damn...

import { render, MountableElement } from 'solid-js/dom';
import { getByTestId } from '@testing-library/dom';

import Hello from 'components/Hello';

test('Text should exist', () => {
  const testMessage = 'Test Message';
  const el = document.createElement('div');
  el.setAttribute('id', 'container');
  render(() => <Hello title={testMessage} />, el as MountableElement);
  expect(getByTestId(el as HTMLElement, 'hello-div')).toHaveTextContent(testMessage);
});

PASS src/components/tests/Hello.tests.tsx √ Text should exist (10 ms)

I'll create a repo with the initial boilerplate, maybe it could be adapted to be a minimal TypeScript starter. It's missing a few things, but I don't think there's a lot of those. I know that create app way is popular, but I prefer a hand written webpack configuration.

ryansolid commented 4 years ago

@high1 Did you make any progress?

I made something really basic to point people as the pure baseline: https://github.com/ryansolid/solid-ts-webpack But realistically there is so much to add. I couldn't really call it a starter. But now atleast someone can get Solid with TypeScript working with a Context based store to boot.

high1 commented 4 years ago

I'll upload what I have, and give you a link to the repo. Haven't made much progress, was swamped with work. I'm willing to improve it, and to take a look at Snowpack 2 when I can.

high1 commented 4 years ago

Here is the link - Solid-typescript-starter. Somethings are finished, some are not - it's a work in progress, but I think it's usable. I'm willing to improve it, and will be listening to any feedback. Is there a way to contact you via some official solid communication channel, to avoid noise inside issues? There are a few ides that could be worked on to improve user experience, which is needed at this point, I think.

ryansolid commented 4 years ago

@high1 for sure it might be easiest to start the conversation via a private twitter or gitter message since I need to get your email to invite you to the slack we've set up. I haven't setup the auto invite on slack yet (still working with the guy who is building the logo/site). But I think ultimately that will be the better place for conversations like these.

ryansolid commented 3 years ago

I've improved the docs to include a projects section where I list some good starters, https://github.com/ryansolid/solid/blob/master/documentation/resources/projects.md#starters. Create Solid will drastically change in the future but it will likely remain a larger batteries included template. But now we have a listing of alternatives. Including Rollup, Webpack, Parcel, Snowpack, and Vite.