Is SSI currently working with nodejs projects?

I’ve been fiddling with both alternatives and I think EJS seems like a good choice.

Not only you solve the SSI but you set the grounds for this:


(Pending AC integration if it’s decided to be implemented). But at least it’s usable in code.

Using .ejs files will also seem more natural to people transitioning from PHP as you say.

Route to ejs file

app.get('/mypage', function (req, res) {
    res.render('pages/mypage');
});

Then inside mypage.ejs

<%- include ('partials/mypartial') %>

And bam SSI…plus templates…with layouts, pages and partials.

I just finished migrating my i18next SSI using ejs partials and it works out of the box.

3 Likes

That is exactly what we plan to do :slight_smile:

2 Likes

I don’t know if this will be useful or not when you start integrating ejs with Wappler, but this is how I am structuring my app being ported to nodejs with ejs as templating system.

And the changes I had to do to make it work.

server.js

...
app.set('view engine', 'ejs');
...

routes.js

Changed file send for rendering. Static are served from public folder so just having the file extension html as set in config.js seems enough for Express to look into the public folder when routing.

...
if (route.url) {
    app[route.method || 'get'](route.path, (req, res) => {
        res.render(route.url); 
    });
}
...
...
    //View route. It will look in the the default /views folder
    {
      "path": "/register", 
      "url": "pages/authentication/register"
    },
    //Static route. It will look in /public as file extension is html
    {
      "path": "/settings",
      "url": "/settings.html"
    }
...

Edit: Obviously I will port yet again to follow whatever requirements are needed by the final implementation. But as I just wanted to fiddle with ejs I thought I would share my structure strategy.

1 Like

We have almost the same implementation as you. We will use ejs as view engine. Templates will be located in the views folder, so the same as your example.

The routes will be a bit different, here an example what can be added to the routes.json

  // static route
  {
    "path": "/about",
    "url": "about.html"
  },
  // view route
  // template is the ejs to render
  // data (optional) is the serverconnect action that is used as data source
  {
    "path": "/register",
    "template", "auth/register",
    "data": "auth/register"
  },
  // serverconnect route
  // exec is the serverconnect action to execute
  {
    "path": "/data.json",
    "exec": "data"
  },
  // redirect
  {
    "path": "/oldpage",
    "redirect": "/newpage"
  }

Routes to serverconnect actions will also be auto generated and are available under /api/{action}.

Files in the public folder are directly accessible, also without the .html. So /about.html is accessible under /about. The root path / will automatically look for index.html as default.

3 Likes

Those additional keys make a lot of sense. Thanks for the extended info.
I can continue with the porting knowing that I can easily adapt what I do now to the final implementation.
It also gives a good head start to those that also start porting now.

I suggest not to make changes in the js files from us, but create you own. Then require them in the index.js. We probably going to support an easier way to implement your own code.

Code currently in the index.js:

const server = require('./lib/server');

server.start();

server has the following properties:
server.server: http.Server instance
server.app: express app instance
server.io: will give access to socket.io when implemented
server.start(): starts the server

So you could change the file to:

const server = require('./lib/server');
require('myServer')(server);
server.start();

and then have a myServer.js like:

const favicon = require('serve-favicon');
const path = require('path');

module.exports = (server) => {
  // custom code here, for example add your own express middleware
  server.app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
};

This should be the best way at this moment, we try not to change the index.js and other files are being changed almost every update. Also if the index would change, it only holds a require to your implementations, so that you do not loose your custom code. Of course this can change since it is still being Beta.

2 Likes

hey guys! I think you are thinking to jump to 4.0 before wappler 3.0 is over :slight_smile:

3 Likes

Actually I was not planning at all deviating from the standard you implement. When you release the final version I will adapt my structure and logic to fit in your implementation.

I just modified these file only to be able to continue working on the port. What I meant was that I am glad I saw your plans for ejs and SSI because I can revert fairly easy my current implementation to fit it into yours.

Although again, the extended information is very helpful now and for the future. So thanks for that.

Edit: Actually I did implement your suggestion because I see myself using this in the short term. Double thanks!

Looking forward for that. Would that be exclusive to nodejs server model or are you talking generally?

It is specific for the nodejs server model, with php and asp you could just upload your own php/asp files and it worked, with node this is different.

1 Like

or 5.0 , internal docker is the next big one I believe

2 Likes

SSI is part of Wappler.io concept, currently if you use SSI with nodejs project you will see that it’s not working, however it’s present on the interface. With php project SSI is handled, they added nodejs and SSI is not handled and they are working to make nodejs project work as well as php project. So i think that are thinking about making the v3 beta a stable version. Because 3.0 is not over if such thing as SSI is not implemented.

1 Like

I think it was a joke and had nothing to do with SSI actually :slight_smile:

1 Like

Just not everyone has a Meme Master badge… :smile:

1 Like

1 Like

@patrick

Would you be able to squeeze an optional key called options(or whatever name feels appropriate) for ejs related routes?

I can foresee a need to send specific data to ejs files(i.e. layouts) when defining routes. It could be similar to the args in the run js flow action.

Those options would be nice for something like this. Take into consideration that this is following my scribbled approach for routing and not the final one you will implement.

routes.json

{
      "path": "/forgot",
      "url": "pages/authentication/layout",
      "options": {
        "id": "forgot", //Pass the body id attribute value.
        "content": "_forgot" // Render the content partial in the layout
      }
    },

route.js

if (route.url) {
                app[route.method || 'get'](route.path, (req, res) => {
                    res.render(route.url, route.options);
                });

My layout file.

<!DOCTYPE html>
<html lang="en">

<head>
	<%- include ('../../partials/_head') %>
</head>

<body class="application application-offset" is="dmx-app" id=<%= id %> dmx-show="translationLoaded">
	<!-- Application container -->
	<div class="container-fluid container-application">
		<!-- Content -->
		<div class="main-content position-relative">
			<!-- Page content -->
			<%- include (content) %>
			<!-- Footer -->
			<%- include ('../../partials/footer') %>
		</div>
	</div>
	<!-- Scripts -->
	<%- include ('../../partials/_footerjs') %>
</body>

</html>

It was quite straightforward to implement a layout system. There are one or two node modules out there that implement blocks and layouts but you actually don’t need that much to implement a simple system.

1st Edit:

I know this has further implications with App Connect design panel that would need further adaptation and can’t be done without considering how to edit a partial file as an App Connect page. Similar to old SSIs.

2nd Edit:

I can’t add more than 3 consecutive replies or I will be sent to the discourse spam jail.

@patrick this is also how I implemented adding JS files from partials to the head of the layout. In case it inspires you for a better way. My implementation is quite simple and I need to double check that if I call a getScripts from another layout file it only loads scripts that pertain to that layout and not from previous.

partial

<% addScripts(['formatters.js', 'zxcvbn/4.4.2/zxcvbn.js', 'js-sha1/0.6.0/sha1.min.js']) %>
<div class="page-content">
...

layout

<head>
	<%- include ('../../partials/_head') %>
	<%- getScripts() %>
</head>

server.js (SO copypasta)

//Add scripts 
app.locals.scripts = [];
app.locals.addScripts = function (all) {
    app.locals.scripts = [];
    if (all != undefined) {
        app.locals.scripts = all.map(function (script) {
            console.log(script);
            return "<script src='/js/" + script + "'></script>";
        }).join('\n ');
    }

};
app.locals.getScripts = function (req, res) {
    return app.locals.scripts;
};

How far is SSI for Wappler NodeJS away from implementation?

A post was split to a new topic: Docker missing mapping to the new NodeJS views

You can check the docs for what’s being implemented in beta 4:

More options and improvements coming in the next versions.