Closed mortenson closed 7 years ago
The entire compiler is separated from node, and it passes around a sys
object. In the case of running stencil from node, it runs the js file in bin
, which creates the node sys
object, and passes that to the compiler.
Please take a look at @stencil/core/server
and @stencil/core/compiler
. Hope that helps, thanks
@adamdbradley That helps, but I'm not sure if all of Stencil's codebase is just using the public sys
methods, which would make writing my own really difficult.
I found an example of this here: https://github.com/ionic-team/stencil/blob/master/src/compiler/util.ts#L56, sys.fs.readFile
is used, which assumes that sys.fs
is available and that it's an instance of the fs
Node package. It looks like many other parts of the codebase also directly access sys.fs
: https://github.com/ionic-team/stencil/search?utf8=%E2%9C%93&q=config.sys.fs&type=
As a result of this, even if I implemented a version of sys
for v8js, I wouldn't have guarantees that only the public methods defined by that Object will be used by the compiler.
References to other Node packages are also used in the compiler, i.e sys.path
and sys.url
. While the concept of having an abstract sys
Object is good, the current compiler code is still strongly coupled to having specific Node packages and behavior present. I would essentially have to mock all public methods of multiple Node packages to make this work.
Right, you would provide your own sys
object, and inside of your functions they would do their way of file reads, write, path joins, etc. But the compiler only knows to call sys.fs.readFile
, but however it got the data it is not involved with.
The problem I have with jumping into this work is that there's no API contract with the code using sys
- I have no awareness of what methods I need to mock in sys.fs
, sys.path
, etc. The code that uses sys
is implicitly dependent on Node, since it expects properties of sys
to be specific Node packages. As it stands now I would have to mock entire Node packages in v8js, which would be an enormous undertaking.
Vue.js offers is a single JS file for SSR, which has no dependencies on Node and no per-environment mocking required to use it. React follows a similar pattern in its v8js example: https://github.com/reactjs/react-php-v8js, no mocking of Node packages is required to SSR React components.
The entire sys object and what functions go on it is all within typescript. https://github.com/ionic-team/stencil/blob/2c11c7df6c612ae84ff7d5aa39413617ff6c2351/src/util/interfaces.ts#L1020-L1129
Ah, I missed the interface before: https://github.com/ionic-team/stencil/blob/master/src/util/interfaces.ts#L1020
I don't think I'll be able to work on this, the time required to re-write all these methods, or make the Node packages work with v8js, is more than I have available.
I'm submitting a:
Current behavior:
The current server side rendering code relies on a Node environment to function, which makes it difficult to run in other Javascript contexts like PHP's v8js.
Expected behavior:
If Stencil distributed a standalone version of the SSR code without using any Node-specific features (ex: globals like require/process/__dirname, filesystem access), it would be a great start to having support for SSR in other environments.
Related code:
I've set up a repository that Stencil contributors can use to test SSR with v8js, which should hopefully kick-start this development. The repository and instructions to use it can be found here: https://github.com/mortenson/stencil-v8js. Running the example PHP file currently throws an error due to the Node dependencies in the SSR code.
Other information:
Vue.js just added SSR support, specifically tested in v8js. You can see the documentation for this here: https://gist.github.com/yyx990803/9bdff05e5468a60ced06c29c39114c6b#environment-agnostic-ssr