-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
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
Proposal: expose Ghost as reusable express middleware #827
Comments
That is way more advanced than ... although good idea. Why is your avatar a Novell Netware logo, by the way? :) |
We do intend to refactor to make this possible in the future 👍 |
Just for reference sake, this came in as a request on the forum today as well: https://en.ghost.org/forum/installation/91-can-i-use-ghost-as-a-module-in-an-existing-express-js-application |
+1 |
+1 |
2 similar comments
+1 |
+1 |
Adding +1 to an open and scheduled issue achieves nothing but sending everyone watching this repo an email. It is very counter productive. If you want the feature, then by all means contribute the code. We understand that this is a desired feature, if we didn't this wouldn't be open & scheduled. |
I don't think it is counter productive. Contributing to the project means I have to read the source code. This issue is open for 6 months. Achieving this functionality would have the biggest impact for Ghost and its community rather than releasing v0.4.(x+1), that looks more than just an opinion. Lastly, thanks for all the Ghost commits you've made so far. It's the simplest "out-of-the-box" solution to blog I've ever used. |
How do you figure this - what impact do you think it will have exactly? Quite clearly, none of the people who want this particular feature are willing to contribute to the project. |
@izelnakri It's also notable that you didn't give any argument why a |
Guess code speaks louder than +1's, huh.
No mean feat I'm sure. I've used instances of HTTPServer that connect middleware can expose in the past to hand off routes like this with much success, but doesn't seem appropriate here. I'm struggling to see what this export would look like? Can an one express instance be bound to another? It's probably worth figuring how this should work before a member of your community spends time trying to hack something together that doesn't work for you guys.. |
I've long wanted this implemented as well but it's easier said then done.
This is the same road block I encounter when trying to conceptualize a solution. The solution in theory is exactly as you say:
But again, as you said, harder done than desired :). I think the light to re-visit this is getting near as there's been a lot of refactoring work done that has made the path to a solution easier to find. However we're not there yet. Hang tight, it'll find its way into the project eventually! And if you can't wait please do hop into IRC. I'd be overjoyed to discuss some strategies on how to tackle this issue. |
Just saw that Express 4.0 has some new features that may make this also easier to accomplish. Check out this explanation of the new express router. Exciting! |
This looks pretty promising! |
Hi! Sometimes I aimlessly browse around GitHub. I just happened to run across this issue. Having Ghost available for mounting in |
@dougwilson Making Ghost work as express middleware is something we really want to do. Although it wouldn't provide anything for the majority of our user base, I think it would help us be more appealing to other node developers and perhaps even drive contributions. The main problem we have is the basic structure of the app - an awful lot happens on boot, including starting the server. Some of this needs breaking down into smaller pieces. Ghost does already support being mounted on subdirectory, so I think that's one of the big pieces - being able to create a node app, and then use Ghost as middleware to serve '/blog' for example. If you have time to look through Ghost's initialisation process and suggest how we can get from A to B, that would be super helpful, and very much appreciated. I know that @hswolff is very keen to get this in, so perhaps he has some more specific questions for you. |
I've been thinking about this problem a lot recently. The most straightforward idea I have of solving this issue involves a fair amount of refactoring, centered around the idea that every module within Ghost must be instantiated to be used as opposed to just being required to be used. This would come in hand with a Ghost 'class' that would be instantiated for each middleware instance, and which would in turn instantiate each module that Ghost requires for a working application instance. Would love to hear some preliminary thoughts on that architecture idea @ErisDS. How we get to there will be done slowly, migrating/refactoring one module at a time (i.e. models, config, basically every directory is what I think of as a module). |
Yes, I definitely need to do this. |
👍 to everything @hswolff said. One thing to keep in mind is that we have killed the ghost singleton just a few weeks ago and we should beware from bringing it back to life again. |
Making
or
would be much more convenient then the current updating process is: |
@martinsookael It is totally possible to setup Ghost that way right now if you want to. This issue is about making Ghost work as express middleware so that you can use it as part of a larger express application. |
@hswolff I know we spoke about this in IRC, and we now have #3815 merged which is kind of step 1 towards making this work. I don't disagree with any of what you have described, in fact it sounds a lot like what is described in #2182 and it definitely needs to be done. What I'm not sure about though, is why it is a prerequisite to exposing Ghost as middleware? Do you feel the approach in #3849 will have problems unless this is done? |
closes TryGhost#827 TryGhost#3849 - Ghost can now be mounted as middleware in another Express app by `app.use('/blog', require('ghost/as-middleware')(ghostConfigHash));` - Update messaging to account for server versus middleware. - Allow access to Ghost's initialization-complete promise through the `.ghostPromise` property added to the middleware instance returned. (Neither the framing app used for functional tests nor an example Express app showing Ghost used as middleware needs this, but examples of its use can be found in `test/unit/as_middleware_spec.js`.) - When used as middleware, `ghostConfigHash` should not contain `url` or a `server` block. - Base URL and path for Ghost determined dynamically from the .mountpath and request information provided by Express. - Ghost configuration can contain `generate404s` and `generate500s` keys. When their values are `false`, Ghost will no longer serve the associated pages. - Created new grunt task `test-middleware-functional` that runs the `test-functional` tests against a test server including Ghost as middleware (plus a number of other tasks/assets needed to support). Did _not_ add this to the set of tasks run by `grunt validate` for fear of impact on build times. Design issues: - I'm not necessarily happy with making Ghost's initialization promise available as a property of the Express middleware instance we return, but it seemed like the least of evils, and I'm not aware of any other Express component that has this need reference for guidance. Any alternative suggestion would be welcome. Refactors: - Validation of the content of Ghost's configuration was moved out of the file-loading method and is now invoked by `config.init` so that checks apply to both files and passed-in configuration hashes. - The entry `asMiddleware:true` is automatically added to the config when Ghost is initialized through the middleware entry point, so that internal code that only operates in this case can test for an explicit configuration. - `checkNodeVersion()` was moved out of `ghost-server.js` and into `utils/startup-check.js` so that it could be shared between server and middleware configurations of Ghost. References: - The individual commits squashed into this PR are available on the branch git://github.com/gleneivey/Ghost.git#separate_middleware_entry_point - A trivial example Express application that incorporates Ghost as a middleware component is in https://github.com/gleneivey/example-express-with-ghost-middleware - A wiki page that may be copied into the main Ghost wiki, describing how to configure/use Ghost as middleware is available at https://github.com/gleneivey/Ghost/wiki/Using-Ghost-as-Express-Middleware
closes TryGhost#827 TryGhost#3849 - Ghost can now be mounted as middleware in another Express app by `app.use('/blog', require('ghost/as-middleware')(ghostConfigHash));` - Update messaging to account for server versus middleware. - Allow access to Ghost's initialization-complete promise through the `.ghostPromise` property added to the middleware instance returned. (Neither the framing app used for functional tests nor an example Express app showing Ghost used as middleware needs this, but examples of its use can be found in `test/unit/as_middleware_spec.js`.) - When used as middleware, `ghostConfigHash` should not contain `url` or a `server` block. - Base URL and path for Ghost determined dynamically from the .mountpath and request information provided by Express. - Ghost configuration can contain `generate404s` and `generate500s` keys. When their values are `false`, Ghost will no longer serve the associated pages. - Created new grunt task `test-middleware-functional` that runs the `test-functional` tests against a test server including Ghost as middleware (plus a number of other tasks/assets needed to support). Did _not_ add this to the set of tasks run by `grunt validate` for fear of impact on build times. Design issues: - I'm not necessarily happy with making Ghost's initialization promise available as a property of the Express middleware instance we return, but it seemed like the least of evils, and I'm not aware of any other Express component that has this need reference for guidance. Any alternative suggestion would be welcome. Refactors: - Validation of the content of Ghost's configuration was moved out of the file-loading method and is now invoked by `config.init` so that checks apply to both files and passed-in configuration hashes. - The entry `asMiddleware:true` is automatically added to the config when Ghost is initialized through the middleware entry point, so that internal code that only operates in this case can test for an explicit configuration. - `checkNodeVersion()` was moved out of `ghost-server.js` and into `utils/startup-check.js` so that it could be shared between server and middleware configurations of Ghost. References: - The individual commits squashed into this PR are available on the branch git://github.com/gleneivey/Ghost.git#separate_middleware_entry_point - A trivial example Express application that incorporates Ghost as a middleware component is in https://github.com/gleneivey/example-express-with-ghost-middleware - A wiki page that may be copied into the main Ghost wiki, describing how to configure/use Ghost as middleware is available at https://github.com/gleneivey/Ghost/wiki/Using-Ghost-as-Express-Middleware
closes TryGhost#827 TryGhost#3849 - Ghost can now be mounted as middleware in another Express app by `app.use('/blog', require('ghost/as-middleware')(ghostConfigHash));` - Update messaging to account for server versus middleware. - Allow access to Ghost's initialization-complete promise through the `.ghostPromise` property added to the middleware instance returned. (Neither the framing app used for functional tests nor an example Express app showing Ghost used as middleware needs this, but examples of its use can be found in `test/unit/as_middleware_spec.js`.) - When used as middleware, `ghostConfigHash` should not contain `url` or a `server` block. - Base URL and path for Ghost determined dynamically from the .mountpath and request information provided by Express. - Ghost configuration can contain `generate404s` and `generate500s` keys. When their values are `false`, Ghost will no longer serve the associated pages. - Created new grunt task `test-middleware-functional` that runs the `test-functional` tests against a test server including Ghost as middleware (plus a number of other tasks/assets needed to support). Did _not_ add this to the set of tasks run by `grunt validate` for fear of impact on build times. Design issues: - I'm not necessarily happy with making Ghost's initialization promise available as a property of the Express middleware instance we return, but it seemed like the least of evils, and I'm not aware of any other Express component that has this need reference for guidance. Any alternative suggestion would be welcome. Refactors: - Validation of the content of Ghost's configuration was moved out of the file-loading method and is now invoked by `config.init` so that checks apply to both files and passed-in configuration hashes. - The entry `asMiddleware:true` is automatically added to the config when Ghost is initialized through the middleware entry point, so that internal code that only operates in this case can test for an explicit configuration. - `checkNodeVersion()` was moved out of `ghost-server.js` and into `utils/startup-check.js` so that it could be shared between server and middleware configurations of Ghost. References: - The individual commits squashed into this PR are available on the branch git://github.com/gleneivey/Ghost.git#separate_middleware_entry_point - A trivial example Express application that incorporates Ghost as a middleware component is in https://github.com/gleneivey/example-express-with-ghost-middleware - A wiki page that may be copied into the main Ghost wiki, describing how to configure/use Ghost as middleware is available at https://github.com/gleneivey/Ghost/wiki/Using-Ghost-as-Express-Middleware
closes TryGhost#827 TryGhost#3849 - Ghost can now be mounted as middleware in another Express app by `app.use('/blog', require('ghost/as-middleware')(ghostConfigHash));` - Update messaging to account for server versus middleware. - Allow access to Ghost's initialization-complete promise through the `.ghostPromise` property added to the middleware instance returned. (Neither the framing app used for functional tests nor an example Express app showing Ghost used as middleware needs this, but examples of its use can be found in `test/unit/as_middleware_spec.js`.) - When used as middleware, `ghostConfigHash` should not contain `url` or a `server` block. - Base URL and path for Ghost determined dynamically from the .mountpath and request information provided by Express. - Ghost configuration can contain `generate404s` and `generate500s` keys. When their values are `false`, Ghost will no longer serve the associated pages. - Created new grunt task `test-middleware-functional` that runs the `test-functional` tests against a test server including Ghost as middleware (plus a number of other tasks/assets needed to support). Did _not_ add this to the set of tasks run by `grunt validate` for fear of impact on build times. Design issues: - I'm not necessarily happy with making Ghost's initialization promise available as a property of the Express middleware instance we return, but it seemed like the least of evils, and I'm not aware of any other Express component that has this need reference for guidance. Any alternative suggestion would be welcome. Refactors: - Validation of the content of Ghost's configuration was moved out of the file-loading method and is now invoked by `config.init` so that checks apply to both files and passed-in configuration hashes. - The entry `asMiddleware:true` is automatically added to the config when Ghost is initialized through the middleware entry point, so that internal code that only operates in this case can test for an explicit configuration. - `checkNodeVersion()` was moved out of `ghost-server.js` and into `utils/startup-check.js` so that it could be shared between server and middleware configurations of Ghost. References: - The individual commits squashed into this PR are available on the branch git://github.com/gleneivey/Ghost.git#separate_middleware_entry_point - A trivial example Express application that incorporates Ghost as a middleware component is in https://github.com/gleneivey/example-express-with-ghost-middleware - A wiki page that may be copied into the main Ghost wiki, describing how to configure/use Ghost as middleware is available at https://github.com/gleneivey/Ghost/wiki/Using-Ghost-as-Express-Middleware
closes TryGhost#827 TryGhost#3849 - Ghost can now be mounted as middleware in another Express app by `app.use('/blog', require('ghost/as-middleware')(ghostConfigHash));` - Update messaging to account for server versus middleware. - Allow access to Ghost's initialization-complete promise through the `.ghostPromise` property added to the middleware instance returned. (Neither the framing app used for functional tests nor an example Express app showing Ghost used as middleware needs this, but examples of its use can be found in `test/unit/as_middleware_spec.js`.) - When used as middleware, `ghostConfigHash` should not contain `url` or a `server` block. - Base URL and path for Ghost determined dynamically from the .mountpath and request information provided by Express. - Ghost configuration can contain `generate404s` and `generate500s` keys. When their values are `false`, Ghost will no longer serve the associated pages. - Created new grunt task `test-middleware-functional` that runs the `test-functional` tests against a test server including Ghost as middleware (plus a number of other tasks/assets needed to support). Did _not_ add this to the set of tasks run by `grunt validate` for fear of impact on build times. Design issues: - I'm not necessarily happy with making Ghost's initialization promise available as a property of the Express middleware instance we return, but it seemed like the least of evils, and I'm not aware of any other Express component that has this need reference for guidance. Any alternative suggestion would be welcome. Refactors: - Validation of the content of Ghost's configuration was moved out of the file-loading method and is now invoked by `config.init` so that checks apply to both files and passed-in configuration hashes. - The entry `asMiddleware:true` is automatically added to the config when Ghost is initialized through the middleware entry point, so that internal code that only operates in this case can test for an explicit configuration. - `checkNodeVersion()` was moved out of `ghost-server.js` and into `utils/startup-check.js` so that it could be shared between server and middleware configurations of Ghost. References: - The individual commits squashed into this PR are available on the branch git://github.com/gleneivey/Ghost.git#separate_middleware_entry_point - A trivial example Express application that incorporates Ghost as a middleware component is in https://github.com/gleneivey/example-express-with-ghost-middleware - A wiki page that may be copied into the main Ghost wiki, describing how to configure/use Ghost as middleware is available at https://github.com/gleneivey/Ghost/wiki/Using-Ghost-as-Express-Middleware
closes TryGhost#827 TryGhost#3849 - Ghost can now be mounted as middleware in another Express app by `app.use('/blog', require('ghost/as-middleware')(ghostConfigHash));` - Update messaging to account for server versus middleware. - Allow access to Ghost's initialization-complete promise through the `.ghostPromise` property added to the middleware instance returned. (Neither the framing app used for functional tests nor an example Express app showing Ghost used as middleware needs this, but examples of its use can be found in `test/unit/as_middleware_spec.js`.) - When used as middleware, `ghostConfigHash` should not contain `url` or a `server` block. - Base URL and path for Ghost determined dynamically from the .mountpath and request information provided by Express. - Ghost configuration can contain `generate404s` and `generate500s` keys. When their values are `false`, Ghost will no longer serve the associated pages. - Created new grunt task `test-middleware-functional` that runs the `test-functional` tests against a test server including Ghost as middleware (plus a number of other tasks/assets needed to support). Did _not_ add this to the set of tasks run by `grunt validate` for fear of impact on build times. Design issues: - I'm not necessarily happy with making Ghost's initialization promise available as a property of the Express middleware instance we return, but it seemed like the least of evils, and I'm not aware of any other Express component that has this need reference for guidance. Any alternative suggestion would be welcome. Refactors: - Validation of the content of Ghost's configuration was moved out of the file-loading method and is now invoked by `config.init` so that checks apply to both files and passed-in configuration hashes. - The entry `asMiddleware:true` is automatically added to the config when Ghost is initialized through the middleware entry point, so that internal code that only operates in this case can test for an explicit configuration. - `checkNodeVersion()` was moved out of `ghost-server.js` and into `utils/startup-check.js` so that it could be shared between server and middleware configurations of Ghost. References: - The individual commits squashed into this PR are available on the branch git://github.com/gleneivey/Ghost.git#separate_middleware_entry_point - A trivial example Express application that incorporates Ghost as a middleware component is in https://github.com/gleneivey/example-express-with-ghost-middleware - A wiki page that may be copied into the main Ghost wiki, describing how to configure/use Ghost as middleware is available at https://github.com/gleneivey/Ghost/wiki/Using-Ghost-as-Express-Middleware
closes TryGhost#827 TryGhost#3849 - Ghost can now be mounted as middleware in another Express app by `app.use('/blog', require('ghost/as-middleware')(ghostConfigHash));` - Update messaging to account for server versus middleware. - Allow access to Ghost's initialization-complete promise through the `.ghostPromise` property added to the middleware instance returned. (Neither the framing app used for functional tests nor an example Express app showing Ghost used as middleware needs this, but examples of its use can be found in `test/unit/as_middleware_spec.js`.) - When used as middleware, `ghostConfigHash` should not contain `url` or a `server` block. - Base URL and path for Ghost determined dynamically from the .mountpath and request information provided by Express. - Ghost configuration can contain `generate404s` and `generate500s` keys. When their values are `false`, Ghost will no longer serve the associated pages. - Created new grunt task `test-middleware-functional` that runs the `test-functional` tests against a test server including Ghost as middleware (plus a number of other tasks/assets needed to support). Did _not_ add this to the set of tasks run by `grunt validate` for fear of impact on build times. Design issues: - I'm not necessarily happy with making Ghost's initialization promise available as a property of the Express middleware instance we return, but it seemed like the least of evils, and I'm not aware of any other Express component that has this need reference for guidance. Any alternative suggestion would be welcome. Refactors: - Validation of the content of Ghost's configuration was moved out of the file-loading method and is now invoked by `config.init` so that checks apply to both files and passed-in configuration hashes. - The entry `asMiddleware:true` is automatically added to the config when Ghost is initialized through the middleware entry point, so that internal code that only operates in this case can test for an explicit configuration. - `checkNodeVersion()` was moved out of `ghost-server.js` and into `utils/startup-check.js` so that it could be shared between server and middleware configurations of Ghost. References: - The individual commits squashed into this PR are available on the branch git://github.com/gleneivey/Ghost.git#separate_middleware_entry_point - A trivial example Express application that incorporates Ghost as a middleware component is in https://github.com/gleneivey/example-express-with-ghost-middleware - A wiki page that may be copied into the main Ghost wiki, describing how to configure/use Ghost as middleware is available at https://github.com/gleneivey/Ghost/wiki/Using-Ghost-as-Express-Middleware
closes TryGhost#827 TryGhost#3849 - Ghost can now be mounted as middleware in another Express app by `app.use('/blog', require('ghost/as-middleware')(ghostConfigHash));` - Update messaging to account for server versus middleware. - Allow access to Ghost's initialization-complete promise through the `.ghostPromise` property added to the middleware instance returned. (Neither the framing app used for functional tests nor an example Express app showing Ghost used as middleware needs this, but examples of its use can be found in `test/unit/as_middleware_spec.js`.) - When used as middleware, `ghostConfigHash` should not contain `url` or a `server` block. - Base URL and path for Ghost determined dynamically from the .mountpath and request information provided by Express. - Ghost configuration can contain `generate404s` and `generate500s` keys. When their values are `false`, Ghost will no longer serve the associated pages. - Created new grunt task `test-middleware-functional` that runs the `test-functional` tests against a test server including Ghost as middleware (plus a number of other tasks/assets needed to support). Did _not_ add this to the set of tasks run by `grunt validate` for fear of impact on build times. Design issues: - I'm not necessarily happy with making Ghost's initialization promise available as a property of the Express middleware instance we return, but it seemed like the least of evils, and I'm not aware of any other Express component that has this need reference for guidance. Any alternative suggestion would be welcome. Refactors: - Validation of the content of Ghost's configuration was moved out of the file-loading method and is now invoked by `config.init` so that checks apply to both files and passed-in configuration hashes. - The entry `asMiddleware:true` is automatically added to the config when Ghost is initialized through the middleware entry point, so that internal code that only operates in this case can test for an explicit configuration. - `checkNodeVersion()` was moved out of `ghost-server.js` and into `utils/startup-check.js` so that it could be shared between server and middleware configurations of Ghost. References: - The individual commits squashed into this PR are available on the branch git://github.com/gleneivey/Ghost.git#separate_middleware_entry_point - A trivial example Express application that incorporates Ghost as a middleware component is in https://github.com/gleneivey/example-express-with-ghost-middleware - A wiki page that may be copied into the main Ghost wiki, describing how to configure/use Ghost as middleware is available at https://github.com/gleneivey/Ghost/wiki/Using-Ghost-as-Express-Middleware
Any updates on this in the last 8 months? Is it working? Dead? I will be looking to set up a blog in the very near future and would like to simply integrate it in my existing site, as many have mentioned above. Thanks! |
@anyong I'm not sure where the official support stands at this point. I lost track of how the pull request from @gleneivey was doing. I would like to point out, however, that I already have this working at my own website with a small amount of patch-code. https://www.joshwillik.com/blog/ If you need any help getting it working in your own, feel free to contact me at the email on my Github profile and I'll do my best to help you through it. |
@JoshWillik first of all that is some impressive response time, thank you! Second, and perhaps more importantly, the link in your latest post here from 8 months ago where you've presumably got that patch code is broke. :( |
@anyong The way I proposed is here. It never got much traction, but it is a functional idea. I suspect this code will no longer work exactly as is, but it shouldn't be
|
My pull request is still valid. I've slowed down with how frequently I rebase onto master, so at any moment it may not be a clean merge, but so far the changes in (the relevant areas of) Ghost haven't been significant enough to turn merging into rewriting. I've got it running in a number of places, but installed it here https://myou.pub/b less than two weeks ago. (Also, in this installation I'm using a variant of Casper with Disqus integration--vanilla based on the standard Ghost instructions.) |
Integrating Ghost into an express app is already a possibility. The open PRs and this issue now reflect an 'improvement' to this, which makes it possible to use Ghost as middleware, rather than as a mounted express app. I've really been struggling to spend time reviewing the PRs, because this issue has a major design issue and the consequences require a lot of thought - the positive impact is minimal (mount as middleware instead of app) but the negative impact is hard to judge - will this prevent us from changing other things in future? This issue has been around for a very, very long time and it definitely would be preferable to resolve it. Here's a curve ball question: Is making Ghost work as middleware even the right thing to do and why? Ghost works right now as a mounted App - so you get a whole app including error handling mounted at a particular route. The main difference (I think) with this is that if Ghost doesn't match the route you get Ghost's 404 page rather than Ghost passing back to your own app? |
In my (possibly incorrect, probably biased) opinion, if you want to provide a way to include ghost as a subsection of a larger site, middleware is correct method. ControlWhen you have an existing application, the top-level code must be in absolute control of the way the application functions. The way the nodejs/express community has informally standardized the way modules fit into a larger system takes the following pattern, with very little variation. var parentApp = require( 'express' )()
var api = require( 'api-module' )
var fileUploadModule = require( 'file-upload' )
var notFound = require( './404-handler' )
parentApp.use( '/api', api( <options> ) )
parentApp.use( '/files', fileUploadModule( <options> ) )
parentApp.use( notFound )
parentApp.listen( 8888 ) The thing to notice here is that all functionality happens at the request of the parent application. The parent dictates which route the child will use, it dictates when the application will start and stop. As far as I can read from the documentation, the currently proposed way to mount a ghost blog is as follows. var ghost = require( 'ghost' )
var parent = require( 'express' )()
ghost( <options> ).then( function( blog ){
parent.use( blog )
parent.listen(8888)
}) This method has 2 huge flaws and a big flaw. The first is that the parent application loses all control over what happens to the request after it enters ghost's domain, because the request will never exit ghost's domain. Ghost will send out a 404, no matter what the parent wants. This is annoying for a hobby blogger, and unacceptable in more enterprise settings. The parent has lost control of the request path. Secondly, the parent no longer decides how the application starts and stops. Ghost has hijacked the boot process and forced the rest of the application to bend to the way it does things. It is no longer a well behaved child. Thirdly, even if we were to accept that it's ok for ghost to hijack the boot process, this will confuse beginners and tinkerers who don't fully understand promises and asynchronicity. You'll see baffled and frustrated users who don't understand why var app = require( 'express' )()
require( 'ghost' )().then( function( blog ){
app.use( blog.rootApp )
})
app.use( <thing1> )
app.use( <thing2> ) appends middleware in the seemingly wrong order. SolutionsIn my view, there are two ways forward. If you want to provide the ability to mount ghost at all, it must be as middleware. This is the standard the community has made, and it should be followed unless we have good reason to ignore it (which we don't). If you dislike the additional complexity this adds, move ghost-as-middleware into a side project. I've left the name |
That's a really good question. When I first set out to embed Ghost in a web app, using it as a mounted app didn't work, either, so going with a middleware interface didn't need really strong motivation. Aside from being able to better integrate the app's over-all error handling, I think the bit thing that's lost by going with the sub-app is going back to config.js instead of a hash passed in from the parent app, and it seems like this is unrelated to middleware (could be passed in when the module's entry point is called to get ghostServer). I much prefer config via environment variables, which I'm currently using to build a config hash with environmental. If things stay as-is and I reach a point where the rebase to integrate my changes on top of a new Ghost release is too hard, I'll probably change over to mounting Ghost as an app and make some kind of env-to-config-file widget. |
With regard to config management - there's a separate issue (#4731) which also has a couple of languishing PRs open against it. I think the config issue applies to several use-cases, so it needs solving separately. The one thing that stands out to me most of all when looking at #4101 is that it seems to touch areas that I wouldn't expect. Maybe it'd be worth explaining that in more detail on the PR? I'm thinking perhaps resolving the config issue first (and perhaps splitting out one or two other details from the PR) might help to reduce the surface area of the changes needed to make the middleware PR work. The smaller the footprint, the easier it is to understand the consequences and merge with confidence 😉 |
I'm not sure which areas are the "unexpected" ones, but the things that caught my eye with a quick scan are:
Other questionable stuff? Thanks, |
Well I'm getting ready to dive in over the next couple of days as the time has come for the blog part of my project... I tend to agree with @JoshWillik above. Everything from parameter parsing to i18n to database links to eCommerce to single page apps and more all follow a fairly standard express protocol. If I understand correctly, the main configuration issues for ghost are the database and mail server. The database uses knex, and the authentication backend uses passport. These are both really standard tools that I think many sites have already in use, and I'm sure there are many others who are already using or would like to simply plug in their existing database and authentication mechanisms for ghost - that's certainly what my approach is.
seems like a perfectly reasonable way to do it, this is pretty much how knex/bookshelf work, too. We can do our ghost config outside of app.js and simply require the configured instance and pass it to a middleware function that starts the app and passes 404s to next(). Anyway, I think it would be great if this was plug-and-play like knex/bookshelf is, so I'm happy to help now that I've got some time for it... please let me know if you've got recommendations for what to do since I'm new to the library. In any case, I'll start looking around and see if anything jumps out. Thanks! |
The discussion and movement on this issue has tailed off, largely because it has been very hard to get a full understanding of what we need to change and why. I believe this is also in part because the underlying goal of the issue is effectively solved, even if it's not perfect, and that there's therefore a lot less traction on this idea than there was previously. There is definitely a great deal of refactoring work to be done inside of Ghost's boot, server & middleware code, and I have always felt that a more natural solution to the ghost-as-middleware issue would fall out of its own accord if #2182 and #4172 were fully addressed and if some of the difficulties around configuration & logging were solved properly. I'm going to close this issue as 'done' for the time being, and focus on ensuring there is a clear idea of how the internals of Ghost might be restructured. I believe the goal of restructuring the Ghost internals in a more sensible, reusable, composable, and 'nodey' way is higher priority and more obtainable, and I think once that work is done, if the ghost-as-middleware use case doesn't improve naturally, then we will at least be able to revisit this issue from a better position. |
It would be cool if Ghost could be installed as an npm module, and then used as middleware in any express app. So you could do something like:
Notably both the content directory, and the url it is served from are configurable here. It could also be interesting to experiment with allowing the front-end, admin interface and public API to all be served from separate custom locations.
This would allow all sorts of possibilities such as having multiple Ghost blogs in the same server, and embedding ghost as part of a larger CMS product... Obviously this would need to be in addition to it working standalone, but I don't think that would be too difficult to manage (the standalone version could just be a thin wrapper around the middleware version).
Thoughts?
The text was updated successfully, but these errors were encountered: