I will translate some technical articles again this week, and I plan to translate three articles as follows:

  • Generate Static Websites with Nuxt

  • How Web Content Can Affect Power Usage

  • Writing asynchronous tasks in modern JavaScript (web.dev/off-main-th…)

All the technical articles I translated are stored in a Github repository. If you find them useful, please click on star favorites. Why am I creating this Git repository? The purpose is to learn and follow up the new ideas and technologies of web development by translating foreign Web related technical articles. Git repository address: github.com/yzsunlei/ja…

Static websites are becoming popular again. Information and branding sites no longer need to use content management systems such as WordPress to dynamically update.

With static Site Builder, you can get content from dynamic sources such as passive CMS, apis, and files such as Markdown files.

Nuxt is an excellent static website generator based on vue.js that can be easily used to build static websites. With Nuxt, all you need to do to build a static website from dynamic content is create templates to dynamically display content from dynamic sources such as apis and Markdown files. Then, in the Nuxt configuration file, we define the route statically so that it can generate the content as a static file through the same route.

In this article, we will use Nuxt to build a News site and use https://newsapi.org/’s News API as the content. You must know vue.js before you can build a website using Nuxt, because Nuxt is a framework based on vue.js.

First, we register the API key on the News API website. If we just want to get headlines, it’s free. Let’s start by building the site using the Nuxt CLI. We run it by typing the following command:

npx create-nuxt-app news-website
Copy the code

This will create the initial project file in the news-Website folder. When we run the wizard, we select nothing for the server-side framework, nothing for the UI framework, nothing for the test framework, no generic files for the Nuxt schema, and finally, depending on your situation, whether to include Axios request libraries, code cleaning with Lint and prettify with prettify.

Next, we need to install some packages. We need the @nuxtjs/dotenv package for reading environment variables locally and the country-list library for getting a list of countries on our website. To install them, we run:

npm i @nuxtjs/dotenv country-list
Copy the code

Now we can start building our website. In the default.vue file, we replace the existing code with:

<template> <div> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <nuxt-link class="navbar-brand" to="/">News  Website</nuxt-link> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation" > <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <nuxt-link class="nav-link" to="/">Home</nuxt-link> </li> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" >Headliny by Country</a> <div class="dropdown-menu" aria-labelledby="navbarDropdown"> <nuxt-link class="dropdown-item" :to="`/headlines/${c.code}`" v-for="(c, i) of countries" :key="i" >{{c.name}}</nuxt-link> </div> </li> </ul> </div> </nav> <nuxt /> </div> </template> <script> import { requestsMixin } from "~/mixins/requestsMixin"; const { getData } = require("country-list"); export default { mixins: [requestsMixin], data() { return { countries: getData() }; }}; </script> <style> .bg-light { background-color: lightcoral ! important; } </style>Copy the code

This is the file that defines the layout of our website. We added the Bootstrap navigation bar here. This column contains home page links and a drop-down list of countries. These NuxT-Link components are links to pages that are used to get country/region titles when generating static files. You can get countries from the country-list package in this section by calling a function. In this section, we change the background color of the navigation bar by overwriting the default color of the class. The component at the bottom of this section displays our content.

scriptgetDatastyle.bg-lightnuxttemplate
Copy the code

Next, we create a mixins folder and create a file called requestSmixin-.jsfile. To which we add:

const APIURL = "https://newsapi.org/v2";  
const axios = require("axios");
export const requestsMixin = {  
  methods: {  
    getHeadlines(country) {  
      return axios.get(  
        `${APIURL}/top-headlines?country=${country}&apiKey=${process.env.VUE_APP_APIKEY}`  
      );  
    }, getEverything(keyword) {  
      return axios.get(  
        `${APIURL}/everything?q=${keyword}&apiKey=${process.env.VUE_APP_APIKEY}`  
      );  
    }  
  }  
};
Copy the code

This file contains code to get headlines by country/region and keyword from the News API.

Then, in the Pages folder, we create the Headlines folder, and then in the file Headlines folder, we create the _countrycode.vue file. In the file, we add:

<template> <div class="container"> <h1 class="text-center">Headlines in {{getCountryName()}}</h1> <div v-if="headlines.length > 0"> <div class="card" v-for="(h, i) of headlines" :key="i"> <div class="card-body"> <h5 class="card-title">{{h.title}}</h5> <p class="card-text">{{h.content}}</p> <button class="btn btn-primary" :href="h.url" target="_blank" variant="primary">Read</button> </div> <img :src="h.urlToImage" class="card-img-bottom" /> </div> </div> <div v-else> <h2 class="text-center">No headlines found.</h2> </div> </div> </template> <script> import { requestsMixin } from "~/mixins/requestsMixin"; const { getData } = require("country-list"); export default { mixins: [requestsMixin], data() { return { headlines: [], countries: getData() }; }, beforeMount() { this.getHeadlinesByCountry(); }, methods: { async getHeadlinesByCountry() { this.country = this.$route.params.countryCode; const { data } = await this.getHeadlines(this.country); this.headlines = data.articles; }, getCountryName() { const country = this.countries.find( c => c.code == this.$route.params.countryCode ); return country ? country.name : ""; }}}; </script>Copy the code

In this file, we take the route parameter, countryCode then calls the this.getHeadlines function from that location that we made earlier and included in this component, requestsMixin to get the title from the News API. The results are then displayed in the Bootstrap card in the template section. In the template, we get the country name by finding the country name from the country-list data. If the title is not found, we display a message. In general, if you want to make a page that accepts URL parameters, you must make a file with an underscore as the first character and the variable names of the required URL parameters. So in this example, in _countrycode. vue we use countryCode with the parameter this.$route.params.countrycode.

Next, index.vue in the Pages folder replaces the existing code with:

<template> <div class="container"> <h1 class="text-center">Home</h1> <div class="card" v-for="(h, i) of headlines" :key="i"> <div class="card-body"> <h5 class="card-title">{{h.title}}</h5> <p class="card-text">{{h.content}}</p> <button class="btn btn-primary" :href="h.url" target="_blank" variant="primary">Read</button> </div> <img :src="h.urlToImage" class="card-img-bottom" /> </div> </div> </template> <script> import { requestsMixin } from "~/mixins/requestsMixin"; const { getData } = require("country-list"); export default { mixins: [requestsMixin], data() { return { headlines: [] }; }, beforeMount() { this.getHeadlinesByCountry(); }, methods: { async getHeadlinesByCountry() { const { data } = await this.getHeadlines("us"); this.headlines = data.articles; }}}; </script> <style> </style>Copy the code

This allows us to display the US title on the home page. It works similarly to the _countrycode. vue page, except that we only get the top stories from the US and don’t take the URL parameter to get the top stories from different countries based on the URL.

Next, we create one in the project’s root folder and add the following:

const fs = require('fs')  
fs.writeFileSync('./.env', `API_KEY=${process.env.API_KEY}`)
Copy the code

This allows us to deploy to Netlify because we need.env to dynamically create files based on the input environment variables. In addition, we.env manually create the file and then use the API_KEY as the key and the News API API key as the value.

Next in nuxt.config.js, we replace the existing code with:

require("dotenv").config(); const { getData } = require("country-list"); export default { mode: "universal", /* ** Headers of the page */ head: { title: "News Website", meta: [ { charset: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }, { hid: "description", name: "description", content: process.env.npm_package_description || "" } ], link: [ { rel: "icon", type: "image/x-icon", href: "/favicon.ico" }, { rel: "stylesheet", href: "Https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"}], script: [{SRC: "Https://code.jquery.com/jquery-3.3.1.slim.min.js"}, {SRC: "Https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"}, {SRC: "Https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"}}, /* ** Customize the progress-bar color */ loading: { color: "#fff" }, /* ** Global CSS */ css: [], /* ** Plugins to load before mounting the App */ plugins: [], /* ** Nuxt.js dev-modules */ buildModules: [], /* ** Nuxt.js modules */ modules: [ // Doc: https://axios.nuxtjs.org/usage "@nuxtjs/axios", "@nuxtjs/dotenv" ], /* ** Axios module configuration ** See https://axios.nuxtjs.org/options */ axios: {}, /* ** Build configuration */ build: { /* ** You can extend webpack config here */ extend(config, ctx) {} }, env: { apiKey: process.env.API_KEY || "" }, router: { routes: [ { name: "index", path: "/", component: "pages/index.vue" }, { name: "headlines-id", path: "/headlines/:countryCode?", component: "pages/headlines/_countryCode.vue" } ] }, generate: { routes() { return getData().map(d => `headlines/${d.code}`); }}};Copy the code

In the head object, we changed the title to display the desired title instead of the default title. In Link, we added the Bootstrap CSS, and in Script, we added the Bootstrap JavaScript file and jQuery, which are Bootstrap dependencies. Since we are building a static site, we cannot use BootstrapVue because it is dynamic. We don’t want to use any dynamic JavaScript in the generated output, so we have to use plain Bootstrap. In Modules, we added “@nuxtjs/dotenv” to read environment variables from files that.env created into the Nuxt application. We also added: require(“dotenv”).config(); So that we can add process.env.api_key to this configuration file. We have to do this, so we don’t have to check in the.env file. In env part, we have apiKey: process. The env. The API_KEY | | “”, this is through the use of reading. The dotenv env file API KEY.

In the Router, we defined dynamic routing so that when a user clicks on a link with a given URL or clicks on a link with such a URL, they can be viewed. Nuxt also uses these routes to generate static files. In Generate, we defined a path for Nuxt traversal to generate a static file for a static site. In this case, the route array consists of the routes from the title page we created earlier. It will iterate over them to get their data, then render them and generate files from the rendered results. The folder structure will correspond to the route. Therefore, since our path is/Headlines /:countryCode, the generated artifacts will have that Headlines folder as well as all the country/region codes as the names of the subfolders, and within each folder there will be an index.html with the present content.

Now we are ready to deploy our website to Netlify. Create a Netlify account by going to https://www.netlify.com/. The free plan will meet our needs. The code is then committed to a Git repository hosted on GitHub, Gitlab, or Bitbucket. Then, when you log in to Netlify, click New Site in Git. From there, you can add Git repositories hosted in one of the services. Then, when you are asked to type Build Command, type node./create-env.js && NPM run generate, and the publish directory will be dist.

After that, enter the API key from the. Env file into the Environment Variables section of the site Settings, which you can access by clicking the Environment link on the Build and Deploy menu. Enter API_KEY as the key, and then the News API API key as the value. Then click the Save button.

Once all content is committed and pushed to a Git repository hosted by GitHub, Gitlab, or Bitbucket, Netlify builds and deploys automatically.

Dev. To /aumayeung/g…