To me, the documentations and online resources that the fab academy community has provided are really useful. It offers various ways of thinking and making almost everthing by using open source tools such as mods and OpenSCAD.
As Git is a distributed version-control system, it could be used as a server out of the box. It's shipped with built-in command git daemon which starts simple TCP server running on the GIT protocol. Dedicated Git HTTP servers help (amongst other features) by adding access control, displaying the contents of a Git repository via the web interfaces, and managing multiple repositories. Already existing Git repositories can be cloned and shared to be used by others as a centralized repo. It can also be accessed via remote shell just by having the Git software installed and allowing a user to log in. Git servers typically listen on TCP port 9418.
git init
initialize a repositorygit config --global user.name "Firstname Lastname"
set name for commitsgit config --global user.email "address@site"
set email for commitsgit remote add origin [SERVER_URL]
push to a remot repository (ex. GitHub or GitLab)git add .
stage all changed files to commitgit commit -m "commit message"
commit changesgit push
push changesgit merge [BRANCH_NAME]
merge branchThis project website is built based on React.js framework as its front-end development and Node.js as its back-end by adopting Gatsby framework which can produce static React.js website and makes it possible to host on GitLab Pages.
React.js is a component based programming language, which means that I can reuse the same component such as the Jumbotron
on the top of this page and replace it with another topic title, description, image and date in any other pages I want to show by just calling its component's tag name <WeekLayout />
.
By setting .gitlab-ci.yaml
properly, Node.js backend environment can be installed during the running pipleline. Since the documentation website doesn't need to receive any dynamic data, I made it remain static by adopting Gatsby framework which can produce static React.js website.
There is also an open source package called GitLab Runner which can be used to cooperate with GitLab to run:
Here is the explanation about how my static documentation website works during the GitLab pipeline:
# Using the latest node version provided by Docker images to build the React app.
image: node:latest
# Cache node modules to speed up future builds.
cache:
paths:
- node_modules
# Enables git-lab CI caching. Both .cache and public must be cached, otherwise builds will fail.
- .cache/
- public/
# Name the stages involved in the pipeline.
# Specify the stages. Default stages of a pipeline are: build, test and deploy.
# Order matters.
stages:
- deploy
# Job name for gitlab to recognise this results in assets for Gitlab Pages
pages:
stage: deploy
# The first two lines are the same scripts that I run locally to build the final bundle files.
script:
- npm install # Install all dependencies.
- ./node_modules/.bin/gatsby build # Build for production.
artifacts:
paths:
- public # The built files in the "public" folder for Gitlab Pages to serve.
only:
- master # Only run on master branch.
npm i --save [PACKAGE_NAME]
save below packages"dependencies": {
"gatsby": "^2.24.91",
"gatsby-image": "^2.4.19",
"gatsby-plugin-google-analytics": "^2.3.15",
"gatsby-plugin-manifest": "^2.4.30",
"gatsby-plugin-react-helmet": "^3.3.11",
"gatsby-plugin-sharp": "^2.6.44",
"gatsby-plugin-sitemap": "^2.4.14",
"gatsby-plugin-typography": "^2.5.11",
"gatsby-remark-autolink-headers": "^2.4.0",
"gatsby-remark-copy-linked-files": "^2.3.19",
"gatsby-remark-custom-blocks": "^2.3.14",
"gatsby-remark-embed-video": "^3.0.10",
"gatsby-remark-external-links": "0.0.4",
"gatsby-remark-images": "^3.3.40",
"gatsby-remark-responsive-iframe": "^2.4.17",
"gatsby-remark-table-of-contents": "^0.1.1",
"gatsby-source-filesystem": "^2.3.37",
"gatsby-transformer-remark": "^2.8.47",
"gatsby-transformer-sharp": "^2.5.15",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-helmet": "^6.1.0",
"react-typography": "^0.16.19",
"reactstrap": "^8.6.0",
"typography": "^0.16.19"
}
npm i --save-dev [PACKAGE_NAME]
save below packages for development purpose"devDependencies": {
"env-cmd": "^10.1.0",
"prettier": "2.1.1"
}
"scripts": {
"build": "gatsby build",
"develop": "env-cmd -f .env gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
}
module.exports = {
siteMetadata: {
siteUrl: `https://fabacademy.wantinghsieh.com`,
title: `Wan-Ting Hsieh 謝宛庭 | Fab Academy 2020`,
author: `Wan-Ting Hsieh`,
description:
"Wan-Ting Hsieh's Project Documentation for Fab Academy 2020. The static site is built by React.js + Gatsby + GraphQL + GitLab CI."
},
plugins: [
{ // for specifying the base directory of source files
resolve: `gatsby-source-filesystem`,
options: {
// name: `static`,
// path: `${__dirname}/static`,
name: `src`,
path: `${__dirname}/src`,
},
},
// for automatically gernerating the sitemap
`gatsby-plugin-sitemap`,
{
resolve: `gatsby-transformer-remark`, // access markdown posts
options: {
plugins: [
{
resolve: "gatsby-remark-embed-video",
options: {
width: 800,
ratio: 1.77, // Optional: Defaults to 16/9 = 1.77
height: 400, // Optional: Overrides optional.ratio
related: false, //Optional: Will remove related videos from the end of an embedded YouTube video.
noIframeBorder: true, //Optional: Disable insertion of <style> border: 0
containerClass: 'embedVideo-container' //Optional: Custom CSS class for iframe container, for multiple classes separate them by space
}
},
`gatsby-remark-responsive-iframe`,
// for copying used files (e.g., videos) in markdown posts to the "public" directory
`gatsby-remark-copy-linked-files`,
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 800, // set image max width in the post
linkImagesToOriginal: true // disable/enable the external link to the original size of the image
}
},
// for automactically generating the list of table of contents from hearders in markdown posts
`gatsby-remark-autolink-headers`,
{
resolve: `gatsby-remark-table-of-contents`,
options: {
exclude: "Table of Contents",
tight: false,
fromHeading: 1,
toHeading: 6,
className: "table-of-contents"
},
},
{ // for opening new tabs by clicking markdown URLs
resolve: "gatsby-remark-external-links",
options: {
target: "_blank",
rel: "nofollow"
}
},
{ // for highlighting markdown code blocks
resolve: `gatsby-remark-prismjs`,
options: {
classPrefix: "language-",
inlineCodeMarker: null,
aliases: {},
showLineNumbers: false,
noInlineHighlight: false,
languageExtensions: [
{
language: "superscript",
extend: "javascript",
definition: {
superscript_types: /(SuperType)/,
},
insertBefore: {
function: {
superscript_keywords: /(superif|superelse)/,
},
},
},
],
prompt: {
user: "root",
host: "localhost",
global: false,
},
escapeEntities: {},
},
},
{ // for adding custom block css classes
resolve: "gatsby-remark-custom-blocks",
options: {
blocks: {
gifSize: {
classes: "gifSize",
},
},
},
}
]
}
},
{ // for tracking the number of website views
resolve: `gatsby-plugin-google-analytics`,
options: {
trackingId: "UA-99560507-5",
},
},
// for adding CSS objects in .jsx files
`gatsby-plugin-emotion`,
{ // for customizing website font style
resolve: `gatsby-plugin-typography`,
options: {
pathToConfigModule: `src/utils/typography`,
},
},
// for editing page metadata objects in React.js pages
`gatsby-plugin-react-helmet`,
// for automatically optimizing images in React.js pages
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
{ // for editing favicon, name amd browser background color
resolve: `gatsby-plugin-manifest`,
options: {
name: `Fab Academy 2020`,
short_name: `Fab Academy 2020`,
start_url: `/`,
background_color: `#001133`,
theme_color: `#001133`,
display: `standalone`,
icon: `static/favicon.png`, // This path is relative to the root of the site.
},
},
{ // for visiting the website offline
resolve: 'gatsby-plugin-offline',
options: {
workboxConfig: {
globPatterns: ['**/static*']
}
}
}
],
}
const path = require('path');
// Goal 1: Generate a slug for each post: postName.md -> postname -> /blog/postName
// Goal 2: Generate the blog post page template
// Goal 3: Generate a new page for each post
module.exports.onCreateNode = ({ node, actions }) => {
const { createNodeField } = actions;
if (node.internal.type == 'MarkdownRemark') {
// reduce the link: https://nodejs.org/dist/latest-v14.x/docs/api/path.html#path_path_basename_path_ext
const slug = path.basename(node.fileAbsolutePath, '.md');
createNodeField({
node,
name: 'slug',
value: slug
});
}
}
// 1. Get path to template
// 2. Get markdown data
// 3. Create new pages
module.exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions;
const weekTemplate = path.resolve('./src/templates/weekLayout.jsx');
const res = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`);
res.data.allMarkdownRemark.edges.forEach((edge) => {
createPage({
component: weekTemplate,
path: `/assignment/${edge.node.fields.slug}`,
context: {
slug: edge.node.fields.slug
}
});
});
}
require("prismjs/themes/prism-okaidia.css")
require("prismjs/plugins/line-numbers/prism-line-numbers.css")
require("prismjs/plugins/command-line/prism-command-line.css")
npm run build
build source files in public foldernpm run develop
locally start and listen to the website on port 8000 (http://localhost:8000/)Image optimization is about reducing the file size of the images displayed on a website as much as possible without sacrificing quality so that the load times of a web page remain low. It’s also about image SEO. That is, getting project images and decorative images to rank on Google and other image search engines.
Since I am quite familiar with using Photoshop to process images for printing or design purpose. So I choose it for my initial image optimization. It is intuitive to adjust the scale of an image by inputing the width, height or resolution you want to the image size dialogue box in Photoshop.
After adjusting the width, height and resolution of my images in Photoshop, I then upload the images to a online image compression tool TinyPNG which uses smart lossy compression techniques to reduce the imge size without sacrificing quality of the images.
Here is the reducing percentage of the images used for this week's documentation:
Google PageSpeed Insights is a handy tool to check which parts of your website slow down the performance and give some advice about how to fix it including image compression.
Here is the testing result of my fab academy website: