Gridsome workflow improvements

"Mon projet immo" screenshot

Beside coding the banking card creation tool with Nuxt, I also use Gridsome on a regular basis to create static landing pages ans mini-sites. Both tools offer very convenient abstractions and I couldn’t say if I would prefer one over the other. Recently I’ve been working on a new project that gave me the opportunity to better grasp Gridsome concepts as well as improve my deployment workflow.

The project

I’ve been asking to develop a mini-site for Banque Populaire Rives de Paris (French Bank) that indicate the current status of a client’s real estate loan. Here is the url of the mini-site but you won’t access the core site without a working ID. The client has previously received an email containing a custom URL built with an ID and it should resolve to a page showing its informations and the current step of its loan status. The pages contain mostly static informations except for the dynamic ones (personal client’s datas).

Querying and parsing client’s data

The data is retrieved from a big CSV file updated by Banque Populaire. I started using the excellent papaparse library to parse the CSV on the client side with great performances. Unfortunately I had to step back to process this query on the server side, so that the CSV URL is not publicly exposed.

I wanted to use Node.js but the server is a shared hosting running an Apache server. I tried using a Firebase Cloud Function to handle this but I ran into CORS problem due to parsing a remote CSV file despite trying a lot of workarounds.

I decided to go with PHP using simple chained operations to return the right data subset. Here is the code returned from the post request : 


$userId = $_POST['userId'];

$rows = array_map(function($v){return str_getcsv($v, ';');}, file('./pathto/frisecyberfinal.csv'));
$header = array_shift($rows);
$csv    = array();

// Build array
foreach($rows as $row) {
    $csv[] = array_combine($header, $row);
}

// Filter callback
function filterCallback($var)
{
    if($_POST['userId']) {
        $userId = $_POST['userId'];
        }else{
            throw new Exception("no user id");
        }
    
      foreach($var as $values) {
        if($var['ID'] == $userId) {
        return true;
        }
  }
}

// Final client's subset
$subset = array_filter($csv, filterCallback);

// Returns
try {
    echo json_encode($subset);   
} catch (Exception $e) {
    echo $e;
}

Using dynamic routing

I used a dynamic route to handle the query from the url, so that we get it using $route.params. As it’s a static site, we have to care about redirections. Gridsome offers a way to generate rewrite rules within a loop but proper examples are missing in the docs, plus, it depends from the server. So I chose to handled my redirections manually within a .htaccess (this one works for OVH and handle /dossier to my dossier/_id vue template)


RewriteEngine On
RewriteRule ^dossier/([^/]*)$ dossier/_id.html [NC,L]

Generating page from collections

For the second time, I took advantage of the built-in Gridsome collections feature to generate the core pages containing user’s step info.  As previously mentioned in a passed article, it’s about gathering datas from static files (.md, .json, whatever…) and query them through the Graph QL layer API. We have to create a template (a basic .vue file) in the /template folder, bind it to a declared collection within gridsome.config.js, and add a page-query block to query data from each node. This is a very flexible and convenient way to generate pages from the data, instead of having to manually fetch a bunch of static files. Once again, all this is explained on a clear manner into the Gridsome docs.

Deployment workflow

My deployment platform of choice is Netlify, but in this case, I had to deploy onto a shared hosting server. Until now, I used a very rough process by just dropping my build manually through a FTP client. Handling staging and prod sites version were always tricky.

I finally dove a bit into SSH commands and built a NPM script that handle a build chained with a server deployment. I injected a custom “ENVIRONMENT” variable used within gridsome.config.js to set proper pathPrefix and outputDIr options accordingly to the build type (staging or prod site). SSH is pretty straightforward to understand, it’s just a matter of “ssh user@server” and them, give the password server when asked by the following prompt.

To avoid entering the password everytime we can upload our ssh key (previously generated) on the server using ssh-copy-id user@server.

Here is are my npm scripts: 


"prod": "npm run prodBuild && npm run prodRsync",
"prodBuild": "ENVIRONMENT=production gridsome build && rm dist/.htaccess && rm dist/.DS_Store",
"prodRsync": "rsync -av --omit-dir-times --no-p --delete --exclude=*.php --exclude=.htaccess --exclude 'users' ./dist/ myaccount@ssh.myserver:./myremotepath",

And my custom Gridsome build props :


const customEnvironement = process.env.ENVIRONMENT

let pathPrefix
let outputDir
switch (customEnvironement) {
  case 'staging':
    pathPrefix = '/custom/staging/subfolder/'
    outputDir = 'staging'
    break
  case 'production':
    pathPrefix = '/'
    outputDir = 'dist'
}

module.exports = {
  siteName: 'Name',
  outputDir: outputDir,
  pathPrefix: pathPrefix,
//...
}

Here was the opportunity to have a better understanding over Gridsome APIs, even if there’s still a lot of feature to discover. Anyway I’m always positively surprised to note that my built projects reach a very honorable Lighthouse score (always over 90).

Home