skip to Main Content

I just finished building a PWA using Ionic. Now i am stuck in making PWA SEO enabled.

Since in ionic there is #(Hash location strategy) enabled in ionic and this results in # in all of the urls which doesn’t help at all in SEO.

So to remove # I tried setting Path location strategy {locationStrategy: ‘path’} in AppModule. This removes the # from the url. But when I try to refresh it or go directly to a url, it returns ‘Cannot GET /url’

Few things I read for this problem is to rewrite to index.html in every request made Or try something as follows in node express.

app.get('*', (req, res, next) => {
   if ((req.url.indexOf('#') > -1) ||
      ((req.url.lastIndexOf('.') === -1) ||
      (req.url.indexOf('/', req.url.lastIndexOf('.')) > -1))) {
    req.url = `/#${req.url}`;
  }
next();
});

Both the above will not solve my problem because if I want to access a url directly i.e.. localhost/a/b . The above solutions will rewrite to localhost/home(Base URL) which I don’t want.

2

Answers


  1. Chosen as BEST ANSWER

    Got it working myself.

    So here is the list of things which I did.

    1. Add the following code to each of the page for which you want to add description, keywords

      ionViewWillEnter(){
         try{
             document.querySelector("meta[name='description']").remove();
         } catch (e){
         }
         try{
            document.querySelector("meta[name='keywords']").remove();
         } catch (e){
      
         }
      
         var description = document.createElement('meta');
         description.name = "description";
         description.content = "I am a description";
         document.getElementsByTagName('head')[0].appendChild(description);
      
         var keywords = document.createElement('meta');
         keywords.name = "keywords";
         keywords.content = "Code, Learn, Respect";
         document.getElementsByTagName('head')[0].appendChild(keywords);
      }
      
    2. Now we need to remove # in path of every url because SEO rejects the urls with # in them. In App Module , add {locationStrategy: 'path'} to your App Module as follows :

      IonicModule.forRoot(MyApp, {
        locationStrategy: 'path'
      })
      
    3. Now # is removed from the url. But when you refresh or directly access the url, this wont work because this is expected behaviour for any SPA Because when you refresh the page , server tries to find the page linked to the URL. For eg: if you hit localhost/abc , then server tries to find abc/index.html which actually doesn't exist.So to resolve this , you have wrote configurations on my server i.e to point every request to index.html . I am using node express server to deploy your pwa. Use the following code to route every request to index.html -

      var express = require('express');
      var path = require('path')
      var app = express();
      app.use(express.static(path.resolve(__dirname, "www")));
      
      app.use('/*', function(req, res){
         res.sendFile(__dirname+ '/www' + '/index.html');
      });
      
      app.set('port', process.env.PORT || 3000);
      app.listen(app.get('port'), function() {
        console.log("listening to Port", app.get("port"));
      });
      
    4. Also you need to put base href in index.html as '/'.

  2. IONIC with SSR (Server Side Rendering) integrated with Firebase Hosting + Cloud Functions + Prerender.io

    First of all, sorry for my poor English.

    After searching through Deep Web (joking), I found the solution. And the coolest solution was that I was able to integrate my Pioneer Ionic application with Firebase Hosting using Cloud Functions.

    After reading the following topic:

    https://github.com/firebase/firebase-tools/issues/33

    The @TheRoccoB user explains how to host the static Web application in Firebase Hosting and redirect traffic from a URL to Cloud Functions.

    What I did was map the routes that I have to index as:

    {
            "source": "/ shop / **",
            "function": "ssr"
          },
          {
            "source": "/ * / promotions / **",
            "function": "ssr"
          }
    

    Since “ssr” is the name of my function in Cloud Functions. So I used the library https://github.com/prerender/prerender-node to check if the request is from a google crowler, in case I redirect the request to a https://github.com/prerender/prerender server.

    const prerender = express ();
    prerender.use (cors);
    prerender.use (
        require ('prerender-node')
        // .set ('prerenderServiceUrl', 'http: // localhost: 3000')
        .set ('prerenderToken', '** TOKEN **')
    );
    prerender.use (require ('prerender-node'). set ('beforeRender', function (req, done) {
        // do you need to do?
        console.log ('Rendering URL:', req.path);
    done ();
    }));
    prerender.use (require ('prerender-node') set ('afterRender', function (err, req, prerender_res) {
        // do you need to do?
        console.log (req.path + 'rendering completed!');
        console.log ('Errors:', err);
    }));
    prerender.get ('*', (req, res) => {
        console.log ('Calling function for URL:', req.path);
        res.set ('Cache-Control', 'public, max-age = 300, s-maxage = 600');
        res.status (200) .send (fs.readFileSync ('./ www / index.html'). toString ());
    });
    exports.ssr = functions.https.onRequest (prerender);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search