• [技术翻译]使用Nuxt生成静态网站


    本周再来翻译一些技术文章,本次预计翻译三篇文章如下:

    我翻译的技术文章都放在一个github仓库中,如果觉得有用请点击star收藏。我为什么要创建这个git仓库?目的是通过翻译国外的web相关的技术文章来学习和跟进web发展的新思想和新技术。git仓库地址:https://github.com/yzsunlei/javascript-article-translate

    静态网站如今再次流行起来了。信息站和品牌宣传站不再需要使用WordPress之类的内容管理系统来动态更新。

    使用静态网站生成器,您可以从无源CMS,API等动态源以及Markdown文件等文件中获取内容。

    Nuxt是基于Vue.js的出色的静态网站生成器,可轻松用于构建静态网站。使用Nuxt,从动态内容构建静态网站所需要做的就是创建模板,以从API和Markdown文件等动态源动态显示内容。然后,在Nuxt配置文件中,我们静态定义路由,以便它可以通过相同的路由将内容生成为静态文件。

    在本文中,我们将使用Nuxt构建新闻网站,并将使用https://newsapi.org/的News API 作为内容。您必须先了解Vue.js,然后才能使用Nuxt建立网站,因为Nuxt是基于Vue.js的框架。

    首先,我们在News API网站上注册API密钥。如果我们只想获取头条新闻,它是免费的。我们开始来使用Nuxt CLI构建网站。我们通过键入以下命令来运行:

    npx create-nuxt-app news-website
    

    这将在news-website文件夹中创建初始项目文件。运行该向导时,我们不为服务器端框架选择任何内容,不为UI框架选择任何内容,不为测试框架选择任何内容,不为Nuxt模式选择通用文件,最后根据您的情况选择是否包含Axios请求库,使用lint进行代码整理和prettify进行代码美化。

    接下来,我们需要安装一些软件包。我们需要@nuxtjs/dotenv用于在本地读取环境变量的程序包和country-list用于在我们的网站上获取国家列表的库。要安装它们,我们运行:

    npm i @nuxtjs/dotenv country-list
    

    现在我们可以开始建立我们的网站了。在default.vue文件中,我们将现有代码替换为:

    <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>
    

    这是用于定义我们网站布局的文件。我们在此处添加了Bootstrap导航栏。该栏包含主页链接和国家列表的下拉列表。这些nuxt-link组件都是指向页面的链接,这些页面用于在生成静态文件时获取国家/地区的标题。可以通过调用函数从该部分的country-list包中获取国家。在本节中,我们通过覆盖类的默认颜色来更改导航栏的背景颜色。本部分底部的组件将显示我们的内容。

    scriptgetDatastyle.bg-lightnuxttemplate
    

    接下来,我们创建一个mixins文件夹并创建一个名为requestsMixin.jsfile的文件。在其中,我们添加:

    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}`  
          );  
        }  
      }  
    };
    

    该文件包含用于从News API获取按国家/地区和关键字作为标题的代码。

    然后,在pages文件夹中,我们创建headlines文件夹,然后在文件headlines夹中,创建_countryCode.vue文件。在文件中,我们添加:

    <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>
    

    在该文件中,我们接受route参数,countryCode然后从该位置调用我们之前制作并包含在此组件中的this.getHeadlines函数,requestsMixin以从News API获取标题。然后结果将显示在该template部分的Bootstrap卡中。在模板中,我们通过从country-list数据中找到国家名称来获得国家名称。如果找不到标题,我们会显示一条消息。通常,如果要制作一个接受URL参数的页面,则必须制作一个带有下划线作为第一个字符以及所需URL参数的变量名的文件。因此,在此示例中,_countryCode.vue中我们将countryCode使用该参数this.$route.params.countryCode

    接下来,index.vue在pages文件夹中,将现有代码替换为:

    <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>
    

    这使我们可以在主页上显示美国的标题。它的工作原理与_countryCode.vue页面相似,不同之处在于,我们仅获得美国的头条新闻,而不接受URL参数来根据URL获得来自不同国家/地区的头条新闻。

    接下来,我们create-env.js在项目的根文件夹中创建一个,并添加以下内容:

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

    这使我们可以部署到Netlify,因为我们需要.env根据输入的环境变量动态创建文件。另外,我们.env手动创建文件,然后将API_KEY键作为键,将News API API键作为值。

    接下来的nuxt.config.js,我们将现有代码替换为:

    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}`);  
        }  
      }  
    };
    

    在head对象中,我们更改了title以便显示所需的标题而不是默认标题。在link中,我们添加了Bootstrap CSS,在script中,我们添加了Bootstrap JavaScript文件和jQuery,它们是Bootstrap的依赖项。由于我们要构建静态站点,因此不能使用BootstrapVue,因为它是动态的。我们不希望在生成的输出中使用任何动态JavaScript,因此我们必须使用普通的Bootstrap。在modules中,我们添加"@nuxtjs/dotenv"了从.env创建到Nuxt应用程序的文件中读取环境变量的功能。我们还进行了添加,require("dotenv").config();以便我们可以将process.env.API_KEY其添加到此配置文件中。我们必须这样做,所以我们不必检入.env文件。在里面env部分,我们有了apiKey: process.env.API_KEY || "",这是通过使用读取.env文件中的API KEY而获得的dotenv。

    在router中,我们定义了动态路由,以便当用户单击具有给定URL的链接或单击具有此类URL的链接时可以查看它们。Nuxt还使用这些路由来生成静态文件。在generate中,我们定义了Nuxt遍历的路径,以生成静态网站的静态文件。在这种情况下,路由数组由我们之前创建的标题页面的路由组成。它将遍历它们以获取它们的数据,然后渲染它们并从渲染的结果生成文件。文件夹结构将与路线相对应。因此,由于我们path是/headlines/:countryCode,因此生成的工件将具有该headlines文件夹以及所有国家/地区代码作为子文件夹的名称,并且在每个文件夹内将有一个index.html 与呈现的内容。

    现在,我们准备将我们的网站部署到Netlify。通过转到https://www.netlify.com/创建一个Netlify帐户。免费计划将满足我们的需求。然后将代码提交到托管在GitHub,Gitlab或Bitbucket上的Git存储库。然后,当您登录Netlify时,单击Git中的New site。从那里,您可以添加托管在其中一项服务中的Git存储库。然后,当要求您输入Build Command时,输入node ./create-env.js && npm run generate,发布目录将为dist。

    之后,将.env文件中的API密钥输入到网站设置的“环境变量”部分,您可以通过单击“构建和部署”菜单上的“环境”链接来进入。输入API_KEY作为密钥,然后输入News API API密钥作为值。然后单击保存按钮。

    一旦将所有内容提交并推送到由GitHub,Gitlab或Bitbucket托管的Git存储库中,Netlify将自动构建和部署。

    原文链接:https://dev.to/aumayeung/generate-static-websites-with-nuxt-1ia1

  • 相关阅读:
    p1373【奶牛的卧室】
    p1248【交错匹配】(DP)
    QBXT模拟赛T3
    NOIP冲刺班的考试总结
    欧拉回路的一些东西
    一道dp题目
    Blocks
    玩具取名
    Y的积木
    游荡的奶牛
  • 原文地址:https://www.cnblogs.com/yzsunlei/p/12159076.html
Copyright © 2020-2023  润新知