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

Frontend refactor: move everything to imports/ #3231

Merged
merged 19 commits into from Feb 22, 2020

Conversation

zarvox
Copy link
Collaborator

@zarvox zarvox commented Feb 18, 2020

tl;dr move everything to the imports/ folder and take explicit responsibility for load order. Eventually, move toward a model where each file imports everything it depends on, and there are very few imports made strictly for their side-effects to the namespace.

Modern JS project structure and tooling has changed a lot in the past few years, and the layout of the sandstorm shell limits what tools we can readily make full use of. For instance, it would be very nice if we could rely on ESLint to tell us if we're making use of a global that we haven't imported or to eventually use TypeScript to tell us we're failing to handle a possible shape of data.

Meteor has moved to a model where they generally encourage folks to make use of npm over Meteor packages, and Sandstorm already relies on many more npm packages than third-party Meteor packages. I believe the only Meteor packages that we use that are not maintained by either us or by Meteor themselves are the iron:router package and the fourseven:scss package, the latter of which does not even impact JS. In the interest of simplifying the answer to the questions "where does code come from?", we can move our own packages into imports and prefer to use a single npm package.json to pull in dependencies.

This will allow easier refactoring as all load order questions within Sandstorm become answerable in one place -- an explicit series of imports in a single server or client main file. We can over time reduce the number of imports-for-side-effects by restructuring code to only make use of things that it explicitly imports (and thus, that something else explicitly exports). Then, we can burn down the length of the import list in the client/server main files.

This pull request moves all JS code and HTML templates from client/, server/, shared/, lib/, and packages/ to live in reasonable places under imports/. It sets up a single client main.js and server main.js entry point for the client and server, which each explicitly import all the files that Meteor would previously have done in the same load order.

To get the remaining packages into imports, we need to hoist them up in the
reverse order they are loaded.  `blackrock-payments` is a leaf in that
dependency tree; let's lift that one first.

We move Blackrock's Stripe dependency into sandstorm's top-level package.json.
We should be able to swap out Npm.require() for plain old imports.

The two asset files are placed in private/, per the Meteor Guide.
@ocdtrekkie
Copy link
Collaborator

To my knowledge, nobody is currently working on significant frontend work right now. I am not super versed in the JS world, but I feel the shell both should be the easiest place to iterate, and is the part of Sandstorm that I feel has been kept up with the least for a while. Ensuring working on it is more accessible to modern JS developers is a really worthy goal.

Also, hi!

@zenhack
Copy link
Collaborator

zenhack commented Feb 18, 2020

It's exciting to see an old face jump back in.

Generally positive about this change; I am in favor of explicit imports & exports and minimal import-time side effects. As @ocdtrekkie mentions I don't think anyone has any WIP stuff on the shell right now. The stuff I'm working on is on the bridge, @abliss has been working on CI stuff.

Re: typescript, now that we've updated to meteor 1.8.2 I think we can just meteor add typescript and start writing code with .ts extensions.

I'd like to keep the window of "don't touch anything" small if possible though. How long do you think this would take to get past that period?

This is probably a good candidate for reworking later -- rethinking
how we expose loginServices on client and server seems pretty reasonable
given how little logic the two actually appear to share.
This appeared to have a dependency on a particular version of the
content-type package from npm.  We can sort that out separately.

Additionally, this has a Meteor package dependency on
fongandrew:find-and-modify.  I pinned the version because I vaguely recall this
particular library breaking in the past when we tried to update it and don't
want to deal with that right now either.
@zarvox
Copy link
Collaborator Author

zarvox commented Feb 19, 2020

This branch now covers "move all the code into imports/ but still relies on all the side-effect ordering. That said, I wouldn't mind landing what I have here so far if it passes tests; this makes it pretty clear where code is supposed to live going forward. :)

The next steps will be approximately:

  • go through each of the files imported in each main.js for their side effects from top to bottom (and be careful about the ones that are imported on both client and server).
  • for each file:
    • explicitly import everything that file depends on (including all the Meteor packages and whatnot)
    • extract the things they modify in the global namespace into some object or objects that they explicitly export
  • remove the file from the imports in main.js and add imports of the newly-exported symbols in each file in the list that cares about observing those side-effects.

@zarvox zarvox marked this pull request as ready for review February 19, 2020 07:37
@zarvox zarvox changed the title Work-in-progress: frontend refactor Frontend refactor: move everything to imports/ Feb 19, 2020
@zarvox
Copy link
Collaborator Author

zarvox commented Feb 19, 2020

I'm hitting some test failures when I run the testsuite locally, so probably don't merge this quite yet unless you have reason to believe I haven't broken anything. Trying to figure out if they're just flakiness or true issues.

Also, once upon a time we had tests that ran automatically against PRs? Do those still exist?

@ocdtrekkie
Copy link
Collaborator

Four tests currently fail in master. Bit of detail on #3208 comments.

@ocdtrekkie
Copy link
Collaborator

If #3208 gets merged, which it should, since it only fails tests that Kenton also fails when he builds on his machine, then we will have tests run automatically against PRs. The Jenkins server is long gone, but that PR gets tests running under GitHub Actions (which is free! woo!)

@ocdtrekkie ocdtrekkie added the ready-for-review We think this is ready for review label Feb 19, 2020
Turns out we do in fact have a dependency between the two files in that
package.
@zarvox
Copy link
Collaborator Author

zarvox commented Feb 19, 2020

This PR is failing the same four tests locally, plus one more:

 ✖ tests/basic

   - Test title (1.494s)
   Testing if the page title equals "Sandstorm".  - expected "Sandstorm" but got: ""
       at Object.Test title (/home/zarvox/git/sandstorm/tests/tests/basic.js:27:15)
       at _combinedTickCallback (internal/process/next_tick.js:132:7)
   SKIPPED:
   - Test login command

Seems possible that importing a template with a <head><title>Sandstorm</title></head> section doesn't actually apply it to the document, and I need to figure out how to do that with imports.

Imported blaze templates don't appear to propagate <head> correctly, for
whatever reason.  So ignore it and accept that we have one template not in
imports for <head> and <body>.
@zarvox
Copy link
Collaborator Author

zarvox commented Feb 20, 2020

https://www.meteor.com/tutorials/blaze/templates is not particularly helpful here. It appears to be carefully sidestepping what appears to be the fact that importing a template that contains a <head> section does not add it to the on initial pageload by leaving that bit in the template that they leave in client/main.html. After doing likewise, this PR passes the same suite of tests that are passing on master (so the integration tests minus the four known failures detailed in #3208).

@kentonv
Copy link
Member

kentonv commented Feb 22, 2020

Awesome work!

This change will probably require more thorough manual testing than usual, to catch obscure breakages not covered by the tests. But, I think it makes sense to merge now to minimize conflicts with any other work, and then we'll just have to spend some time testing things before the next release.

Also, it sounds like subsequent work will be more incremental and less likely to conflict with any concurrent changes, which is great.

@kentonv kentonv merged commit be43a70 into master Feb 22, 2020
@kentonv kentonv deleted the zarvox-wip-frontend-refactor branch February 22, 2020 17:58
@ocdtrekkie ocdtrekkie removed the ready-for-review We think this is ready for review label Feb 22, 2020
@zenhack
Copy link
Collaborator

zenhack commented Feb 22, 2020

Master now looks like this for me:

Screenshot_2020-02-22 Sandstorm

Did you confirm this was working before merging?

@zenhack
Copy link
Collaborator

zenhack commented Feb 22, 2020

From sandstorm.log:

kj/compat/http.c++:5109: error: HttpService threw exception after generating a partial response; too late to report error to client; exception = kj/compat/http.c++:1851: failed: previous HTTP message body incomplete; can't write more messages
stack: 5747e0 573ba0
kj/compat/http.c++:5048: error: unhandled exception in HTTP server; exception = kj/compat/http.c++:1851: failed: previous HTTP message body incomplete; can't write more messages
stack: 5747e0 57c290
kj/compat/http.c++:5109: error: HttpService threw exception after generating a partial response; too late to report error to client; exception = kj/compat/http.c++:1851: failed: previous HTTP message body incomplete; can't write more messages
stack: 5747e0 573ba0
kj/compat/http.c++:5048: error: unhandled exception in HTTP server; exception = kj/compat/http.c++:1851: failed: previous HTTP message body incomplete; can't write more messages
stack: 5747e0 57c290

@zenhack
Copy link
Collaborator

zenhack commented Feb 22, 2020

False alarm; when fixing the merge conflicts on #3155, somehow I ended up with a changelog.html not part of the repo. Not sure how, but deleting it fixes this.

@kentonv
Copy link
Member

kentonv commented Feb 22, 2020

I think this is because changelog.html is generated during make (based on CHANGELOG.md), and this PR changes the output location of changelog.html, so the old one was left sitting around in our work trees, and Meteor happily incorporated that into the build, leading to a duplicate-defined template, leading startup to throw an exception before registering any routes, hence the Iron Router error page.

@zenhack
Copy link
Collaborator

zenhack commented Feb 22, 2020

Aha, that makes sense.

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

Successfully merging this pull request may close these issues.

None yet

4 participants