1. 前言
1.1. 什么是JAMstack?
JAMstack是指使用JavaScript、API和Markup构建的技术堆栈,JAM是JavaScript、API和Markup的简称,前面第一个字母缩写,JAMstack一种基于客户端JavaScript,可重用API和预构建Markup的现代Web开发架构,需要符合下面三个标准:
- JavaScript:请求/响应周期中的任何动态编程都由JavaScript处理,完全在客户端上运行。这可以是任何前端框架,库,甚至是轻量JavaScript。
- API:所有服务器端进程或数据库操作都被抽象为可重用的API,使用JavaScript通过HTTPS访问。这些可以是定制的或利用第三方服务。
- Markup:模板化标记应该在部署时预先构建,通常使用内容站点的站点生成器或Web应用程序的构建工具。
当我们谈论“堆栈”时,我们不再谈论操作系统,特定Web服务器,后端编程语言或数据库。JAMstack与特定技术无关。这是一种构建网站和应用程序的新方法,可提供更好的性能,更高的安全性,更低的扩展成本以及更好的开发人员体验。
1.2. 什么不是JAMstack?
依赖于客户端和服务器之间紧密耦合的任何项目都不是使用JAMstack构建的。包括:
- 使用服务器端CMS构建的站点,如WordPress,Drupal,Joomla或Squarespace。
- 一个单片服务器运行的Web应用程序,它依赖于Ruby,Node或其他后端语言。
- 单页应用程序,使用同构呈现在运行时在服务器上构建视图。
1.3. 为何选择JAMstack?
-
更好的性能:为什么要在部署时生成页面时等待页面动态构建?当谈到最小化第一个字节的时间时,没有什么能比通过CDN提供的预构建文件更好。
-
快速的部署:可以轻松部署JAMstack网站,而无需经历配置数据库,保护.htaccess等麻烦,只需处理静态文件,因此可以快速在CDN上部署运行。
-
安全性更高:将服务器端进程抽象为微服务API,可以减少攻击的表面区域。您还可以利用专业第三方服务的专业知识。
-
更便宜,更容易扩展:当您的部署相当于可以在任何地方提供服务的一堆文件时,扩展就是在更多地方提供这些文件的问题。CDN是完美的,通常包括扩展他们的所有计划。
-
更好的开发者体验:松散耦合和控制分离允许更有针对性的开发和调试,并且为站点生成器扩展选择CMS选项消除了为内容和营销维护单独堆栈的需要。
1.4. 最佳实践
在构建JAMstack项目时,如果您坚持一些最佳实践,您可以真正获得最大的收益。
1.4.1. 整个项目放在CDN上
因为JAMstack项目不依赖于服务器端代码,所以可以分发它们而不是保存在单个服务器上。直接从CDN服务可以解锁无法超越的速度和性能。您可以推送到边缘的应用程序越多,用户体验就越好。
1.4.2. 一切都在Git中
使用JAMstack项目,任何人都应该能够使用git clone标准过程(如npm install)安装任何所需的依赖项,并准备好在本地运行整个项目。没有要克隆的数据库,没有复杂的安装。这减少了贡献者的摩擦,并且还简化了分段和测试工作流程。
1.4.3. 现代构建工具
充分利用现代构建工具的世界。它可以成为一个面向丛林的丛林,它是一个快速移动的空间,但你希望今天能够使用明天的网络标准,而无需等待明天的浏览器。目前这意味着Babel,PostCSS,Webpack是朋友。
1.4.4. 自动构建
由于JAMstack标记是预先构建的,因此在运行其他构建之前,内容更改不会生效。自动化此过程将为您节省很多挫折感。您可以使用webhook自行完成此操作,也可以使用自动包含该服务的发布平台。
1.4.5. 原子部署
随着JAMstack项目变得非常庞大,新的更改可能需要重新部署数百个文件。一次上载这些一个可能会在进程完成时导致不一致的状态。您可以使用允许您执行“原子部署”的系统来避免这种情况,在上传所有已更改的文件之前,不会进行任何更改。
1.4.6. 即时缓存失效
当构建到部署周期变得经常发生时,您需要知道当部署上线时,它真的会上线。通过确保您的CDN可以处理即时缓存清除来消除任何疑问。
1.5. 如何开始?
使用成熟可靠的静态站点生成器可以在几分钟内构建JAMstack网站和应用,推荐以下几款流行的,新美文使用过,且模板选择较多。
-
Jekyll:一个最早、简单、可扩展的静态站点生成器,得到Github全面支持,可方便免费部署在Github。
-
Hexo:是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页。
-
Hugo:使用go语言开发,最受欢迎的开源静态站点生成器之一,凭借其惊人的速度和灵活性,使用Hugo制作网站变得轻松和灵活。
-
Gatsby:一个基于React的免费开源框架,可以帮助开发人员构建超快速的网站和应用程序,用过之后会对浏览速度发出惊叹。
-
Gridsome:一个Vue.js驱动的现代站点生成器。
2. 简介
Gridsome是一个开源超8K+基于Vue.js超快速创建现代化网站的工具栈,用于创建可在任何地方部署的快速安全的网站。
它使开发人员可以轻松构建现代JAMstack网站。
Gridsome捆绑了一些难以错过的功能,这使它成为最受欢迎的静态站点生成器之一。其中一些功能包括:
- 基于Vue.js - 最简单,最易用的前端框架。
- 通过热加载进行本地开发 - 在开发过程中实时查看更改。
- 基于文件的页面路由 - src/pages中的任何Name.vue文件都是静态路由。
- 动态路由 - src/pages中的任何[param].vue文件都是动态路由。
- 静态文件生成 - 安全,快速地部署到任何CDN或静态Web主机。
- 数据来源 - 从任何Headless CMS,API或Markdown文件中添加数据。
- GraphQL数据层 - 具有集中式数据层的简单数据管理。
- 自动代码拆分 - 将超高性能构建到每个页面中。
- 自动优化的代码 - 开箱即用的代码分割和资产优化。
- 自动页面预取 - 页面在后台加载以便快速浏览。
- 渐进式图像支持 - 自动调整大小,优化和延迟加载图像。
- 插件生态系统 - 查找适合任何工作的插件。
2.1 原理
Gridsome是一个现代的网站开发框架,用于创建可以部署在任何地方的快速,安全的网站。生成静态HTML文件以创建SEO友好的标记,一旦将其加载到浏览器中,该标记就会合并到由Vue.js驱动的SPA中。
源插件从本地文件或外部API获取内容,并将数据存储在本地数据库中。统一的GraphQL数据层使您可以仅从数据库中提取所需的数据,并在Vue.js组件中使用它们。数据在构建时生成并存储为静态JSON。
首先只加载关键的HTML,CSS和JavaScript。接下来的页面会被预取,这样用户就可以在不重新加载页面的情况下快速点击,即使离线时也是如此。
Gridsome会自动优化前端以加载和快速执行blazing。你可以得到代码分割,图像优化,延迟加载,几乎完美的灯塔得分开箱即用。
Gridsome站点通常不连接到任何数据库,并且可以完全托管在全局CDN上。它可以处理数千到数百万次点击,并且不需要昂贵的服务器成本。
Gridsome使用超快速静态站点生成器,JavaScript和API的强大功能来创建令人惊叹的动态Web体验。
Gridsome站点在转换成一个完全由Vue.js支持的SPA之前作为静态HTML加载。这使得搜索引擎能够抓取内容并给出更好的搜索引擎优化排名,并且仍然拥有Vue.js的所有功能。
3. 快速入门
3.1. 先决条件
您应该具有有关HTML,CSS,Vue.js以及如何使用Terminal的基本知识。了解GraphQL的工作原理是有好处的,但不是必需的。
Gridsome需要Node.js(v8.3 +)。
3.2. 安装Gridsome CLI工具
npm install --global @gridsome/cli
3.3. 创建一个Gridsome项目
gridsome create my-gridsome-site #创建一个新项目
cd my-gridsome-site #进入文件夹
gridsome develop #在以下位置启动本地开发服务器 http://localhost:8080
如果我们尝试更改此布局页面上的任何内容,那么我们将看到它会自动更改屏幕上的内容。这是我们之前谈到的Gridsome Hot Reloading功能的结果。
4. 目录结构
基本的Gridsome项目的结构如下:
.
├── package.json
├── gridsome.config.js
├── gridsome.server.js
├── static/
└── src/
├── main.js
├── index.html
├── App.vue
├── layouts/
│ └── Default.vue
├── pages/
│ ├── Index.vue
│ └── Blog.vue
└── templates/
└── BlogPost.vue
4.1. root 目录
-
package.json包含有关项目中安装了哪些插件的信息。 -
gridsome.config.js该文件包含已安装插件的配置和选项。 -
gridsome.server.js该文件是可选的,用于挂接到Gridsome服务器的各个部分。该文件必须导出可以访问API的函数。
4.2. /src 目录
-
Main.js在此处导入全局样式和脚本。该文件还具有可以访问Client API的导出功能。该文件是安装Vue插件,注册组件和指令等的地方。 -
Layouts目录如果要共享页面或模板的一个或多个布局,请在此目录中创建组件。 -
Pages目录该目录中的所有组件均成为您网站的页面。每个页面将根据其.vue文件的位置获得其路径。src/pages/Index.vue将成为您网站的主页,而src/pages/AboutUs.vue将成为example.com/about-us。 -
Templates目录如果要将外部数据源(例如来自WordPress博客的帖子)导入到项目中,则每个帖子都会在此目录中寻找其模板的组件。组件文件的名称必须与GraphQL模式中的节点类型匹配。 -
自定义index.html有时,您将需要覆盖Gridsome用于生成页面的基本HTML模板。Gridsome使这变得非常容易。您要做的就是在src目录中创建一个新的index.html文件。 -
自定义App.vue该App.vue文件是包装所有页面和模板的主要组件。您可以通过App.vue在src目录中拥有自己的文件来覆盖默认文件。如果要在所有页面之间共享布局,则覆盖默认值很有用。
了解有关覆盖App.vue的更多信息
4.3. /static 目录
此目录中的文件将dist在构建期间直接复制到。例如,/ static / robots.txt将位于yoursite.com/robots.txt
- Aliases 在Gridsome中,您可以使用别名~或@链接到文件/src夹内的文件。例如,您可以使用以下命令导入Vue组件
import Card from '~/components/Card'
4.4. 其他目录
-
Assets全局样式,图像,字体和图标通常添加到src/assets目录中。 -
Shared or global components您可以在多个页面或模板中使用的组件可以存储在src/components目录中。 -
Data files您可以将诸如.json或.yaml想要导入到组件中的数据文件存储在src/data目录中。
5. 项目配置
Gridsome需要gridsome.config.js才能工作。插件配置和项目设置都是在这个文件当中。基本配置文件如下所示:
module.exports = {
siteName: 'Gridsome',
siteUrl: 'https://www.gridsome.org',
plugins: []
}
-
siteName 为您的项目设置一个名称。该名称通常在标题标签中使用
-
siteDescription 为您的项目设置描述
-
siteUrl 通常用于设置站点的域的根目录
-
host 运行时主机
-
port 运行时端口
-
outputDir 当运行
gridsome build时,将在其中生成生产构建文件的目录 -
pathPrefix Gridsome假定您的项目是从域的根目录提供的。如果您的项目将托管在名为
/my-app的子目录中,请更改此选项my-app -
titleTemplate 默认
%s - <siteName>,用于设置标题的模板。在页面中设置的元信息,会替换这个%s占位符 -
plugins 通过将插件添加到plugins数组来激活插件
module.exports = {
plugins: [
{
use: '@gridsome/source-filesystem',
options: {
path: 'blog/**/*.md',
route: '/blog/:year/:month/:day/:slug',
typeName: 'Post'
}
}
]
}
-
templates 定义集合的路由和模板
-
metadata 将全局元数据添加到GraphQL schema
-
icon 默认情况下会使用位于
src/favicon.png作为favicon和touchicon。但也可以定义其他路径或大小,图标应为正方形,最小16个像素
module.exports = {
icon: './src/my-icon.png'
}
- configureWebpack 如果该选项是一个对象,它将与内部配置合并。
module.exports = {
configureWebpack: {
// merged with the internal config
}
}
如果该选项是一个函数,它将获得内部配置作为其第一个参数。您可以修改参数或返回一个新的配置对象,该对象将覆盖内部webpack配置。
const merge = require('webpack-merge')
module.exports = {
configureWebpack(config) {
return merge({ /* custom config */ }, config)
}
}
-
chainWebpack 该函数将接收由webpack-chain提供支持的ChainableConfig实例
-
runtimeCompiler 在运行时包括Vue模板编译器
-
configureServer 配置开发服务器
-
permalinks.trailingSlash 启用此选项后,具有动态路由的页面将不包含斜杠,并且服务器上必须具有额外的重写规则才能正常工作。此外,的静态路径不会自动包含尾部斜杠,而应包含在路径中:
<g-link to="/about-us/">About us</g-link>
- permalinks.slugify 使用自定义的Slugify方法。默认slugifyer是
@sindresorhus/slugify。
module.exports = {
permalinks: {
slugify: {
use: 'another-slugify-library',
options: {}
}
}
}
-
css.split 将CSS分成多个块。默认情况下禁用拆分。拆分CSS可能会导致奇怪的行为
-
css.loaderOptions 将选项传递给与CSS相关的加载程序。例如:
module.exports = {
css: {
loaderOptions: {
scss: {
// options here will be passed to sass-loader
},
less: {
// options here will be passed to less-loader
}
}
}
}
6. 页面
页面负责在URL上显示您的数据。
每个页面将静态生成,并具有自己的index.html带有标记的文件。
在Gridsome中创建页面有两个选择:
- 使用file system - 用单文件组件创建页面。
- 使用Pages API - 用编程方式创建页面。
6.1. 基于文件的页面
src/pages目录中的单文件组件将自动转换成它的URL。
文件位置用于生成URL,以下是一些基本示例:
src/pages/Index.vue变成/(首页)src/pages/AboutUs.vue变成/about-ussrc/pages/about/Vision.vue变成/about/visionsrc/pages/blog/Index.vue变成/blog
一个简单的页面组件可能看起来像这样:
<template>
<div>
<h1>Hello, world!</h1>
</div>
</template>
src/pages中的页面通常用于固定网址,例如/about;或用于列出博客文章,例如/blog。
6.2. 编程方式创建页面
可以使用gridsome.server.js中的createPages钩子,以编程方式创建页面。
如果您想从外部API手动创建页面而不使用GraphQL数据层,这很有用。
module.exports = function (api) {
api.createPages(({ createPage }) => {
createPage({
path: '/my-page',
component: './src/templates/MyPage.vue'
})
})
}
6.3. 动态路由
页面可以具有动态路由。对于仅需要客户端路由的页面,动态路由很有用。
例如,用户页面根据URL中的片段,从外部API获取信息。
6.4. 页面元信息
Gridsome使用vue-meta处理有关页面的元信息。
<template>
<div>
<h1>Hello, world!</h1>
</div>
</template>
<script>
export default {
metaInfo: {
title: 'Hello, world!',
meta: [
{ name: 'author', content: 'John Doe' }
]
}
}
</script>
6.5. 自定义404页面
创建一个src/pages/404.vue组件,即可自定义404页面。
7. 集合
集合是一组节点,每个节点都包含带有自定义数据的字段。如果您要在网站上放置博客文章,标签,产品等,则集合很有用。
7.1. 添加集合
集合可以通过Source plugins添加,也可以使用Data Store API自己完成。
集合在development和build期间存储在本地内存数据存储中。
节点可以来自本地文件(Markdown,JSON,YAML等)或任何外部的API。
7.2. 使用Source plugins添加集合
将集合添加到Gridsome的最简单方法是使用Source plugins。
本示例从WordPress网站创建集合。Source plugins的typeName选项通常用于集合名称添加前缀。
// gridsome.config.js
module.exports = {
plugins: [
{
use: '@gridsome/source-wordpress',
options: {
baseUrl: 'YOUR_WEBSITE_URL',
typeName: 'WordPress',
}
}
]
}
您可以在 https://gridsome.org/plugins 上浏览源插件。
7.3. 使用Data Store API添加集合
您可以从任何外部API手动添加集合。
本示例创建一个名为Post的集合,该集合从API获取内容,并将结果作为节点添加到该集合。
// gridsome.server.js
const axios = require('axios')
module.exports = function (api) {
api.loadSource(async actions => {
const collection = actions.addCollection('Post')
const { data } = await axios.get('https://api.example.com/posts')
for (const item of data) {
collection.addNode({
id: item.id,
title: item.title,
content: item.content
})
}
})
}
7.4. 在GraphQL中的集合
每个集合将向 GraphQL Schema 添加两个根字段,这些根字段用于检索页面中的节点。
字段名称是根据集合名称自动生成的。如果为集合命名Post,则在 Schema 中将具有以下可用字段:
- post 通过单个id获取节点。
- allPost 获取节点列表。(可以排序和过滤。)
7.4.1. 自动生成Schema
Schema中的每个集合类型都将具有基于启动时发现的数据自动生成的字段。
这对于简单的项目非常有用,但由于内容已从外部源中删除,因此通常会导致错误,例如缺少字段。您可以使用Schema API定义自己的架构,该架构在数据更改时将保留。
集合的自定义架构类型必须实现该Node接口。
7.4.2. 探索可用的类型和字段
您可以通过在GraphQL资源管理器中打开Schema选项卡来浏览可用字段。
slugify
GitHub:github.com/sindresorhu…
对于URLs、文件名和IDs很实用的Js处理类。它正确处理德语变音符号,越南语,阿拉伯语,俄语,罗马尼亚语,土耳其语等。
安装
npm install @sindresorhus/slugify
用法
const slugify = require('@sindresorhus/slugify');slugify('I ♥ Dogs');
//=> 'i-love-dogs'
slugify(' Déjà Vu! ');
//=> 'deja-vu'
slugify('fooBar 123 $#%');
//=> 'foo-bar-123'