Skip to content

Commit

Permalink
Merge pull request #32 from google/main
Browse files Browse the repository at this point in the history
Merge from upstream
  • Loading branch information
indcoder authored Jul 7, 2021
2 parents 150a15c + c877307 commit e359367
Show file tree
Hide file tree
Showing 28 changed files with 2,583 additions and 2,975 deletions.
1 change: 1 addition & 0 deletions .eleventyignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
.github/
.netlify/
_site/
node_modules/
package-lock.json
Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '45 2 * * 0'

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed

steps:
- name: Checkout repository
uses: actions/checkout@v2

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ node_modules/
js/min.js
js/min.js.map
.vscode/
.netlify/
export
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Based on the awesome [eleventy-base-blog](https://github.com/11ty/eleventy-base-

## Demo

* [Netlify Demo](https://eleventy-high-performance-blog-sample.industrialempathy.com/)
* [Original site this template was based on](https://www.industrialempathy.com/)
- [Netlify Demo](https://eleventy-high-performance-blog-sample.industrialempathy.com/)
- [Original site this template was based on](https://www.industrialempathy.com/)

## Getting Started

Expand All @@ -36,11 +36,13 @@ npm install
```

### 5. Build, serve, watch and test

```
npm run watch
```

### 6. Build and test

```
npm run build
```
Expand All @@ -54,7 +56,7 @@ npm run build

```css
:root {
--primary: #E7BF60;
--primary: #e7bf60;
--primary-dark: #f9c412;
}
```
Expand All @@ -75,7 +77,8 @@ npm run build

- Generates multiple sizes of each image and uses them in **`srcset`**.
- Generates a **blurry placeholder** for each image (without adding an HTML element or using JS).
- Transcodes images to [AVIF](https://en.wikipedia.org/wiki/AV1#AV1_Image_File_Format_(AVIF)) (currently off-by-default due to instability of the encoder) and [webp](https://developers.google.com/speed/webp) and generates `picture` element.
- Transcodes images to [AVIF](<https://en.wikipedia.org/wiki/AV1#AV1_Image_File_Format_(AVIF)>) and [webp](https://developers.google.com/speed/webp) and generates `picture` element.
- Transcodes GIFs to muted looping autoplaying MP4 videos for greatly reduced file size.
- **Lazy loads** images (using [native `loading=lazy`](https://web.dev/native-lazy-loading/)).
- **Async decodes** images (using `decoding=async`).
- **Lazy layout** of images and placeholders using [`content-visibility: auto`](https://web.dev/content-visibility/#skipping-rendering-work-with-content-visibility).
Expand All @@ -102,14 +105,15 @@ npm run build
#### Fonts

- Serves fonts from same origin.
- Makes fonts `display:swap`.
- Makes fonts `display:optional`.

#### Analytics

- Supports locally serving Google Analytics's JS and proxying it's hit requests to a Netlify proxy (other proxies could be easily added).
- Supports sending [Core Web Vitals](https://web.dev/vitals/) metrics to Google Analytics as [events](https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics).
- Support for noscript hit requests.
- Avoids blocking onload on analytics requests.
- To turn this on, specify `googleAnalyticsId` in `metadata.json`.
- To turn this on, specify `googleAnalyticsId` in `metadata.json`. (Note, that this is not compatible with the not-yet-commonly used version 4 of Google Analytics.)

### DX features

Expand Down
68 changes: 0 additions & 68 deletions _11ty/avif.js

This file was deleted.

1 change: 1 addition & 0 deletions _11ty/blurry-placeholder.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ async function getDataURI(src) {
const info = await sizeOf(src);
const imgDimension = getBitmapDimensions_(info.width, info.height);
const buffer = await sharp(src)
.rotate() // Manifest rotation from metadata
.resize(imgDimension.width, imgDimension.height)
.png()
.toBuffer();
Expand Down
53 changes: 32 additions & 21 deletions _11ty/img-dim.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ const sizeOf = promisify(require("image-size"));
const blurryPlaceholder = require("./blurry-placeholder");
const srcset = require("./srcset");
const path = require("path");

const ACTIVATE_AVIF = false;
const { gif2mp4 } = require("./video-gif");

/**
* Sets `width` and `height` on each image, adds blurry placeholder
Expand All @@ -45,6 +44,9 @@ const processImage = async (img, outputPath) => {
src =
"/" +
path.relative("./_site/", path.resolve(path.dirname(outputPath), src));
if (path.sep == "\\") {
src = src.replace(/\\/g, "/");
}
}
let dimensions;
try {
Expand All @@ -60,57 +62,66 @@ const processImage = async (img, outputPath) => {
if (dimensions.type == "svg") {
return;
}
if (dimensions.type == "gif") {
const videoSrc = await gif2mp4(src);
const video = img.ownerDocument.createElement(
/AMP/i.test(img.tagName) ? "amp-video" : "video"
);
[...img.attributes].map(({ name, value }) => {
video.setAttribute(name, value);
});
video.src = videoSrc;
video.setAttribute("autoplay", "");
video.setAttribute("muted", "");
video.setAttribute("loop", "");
if (!video.getAttribute("aria-label")) {
video.setAttribute("aria-label", img.getAttribute("alt"));
video.removeAttribute("alt");
}
img.parentElement.replaceChild(video, img);
return;
}
if (img.tagName == "IMG") {
img.setAttribute("decoding", "async");
img.setAttribute("loading", "lazy");
// Contain the intrinsic to the `--main-width` (width of the main article body)
// and the aspect ratio times that size. But because images are `max-width: 100%`
// use the `min` operator to set the actual dimensions of the image as the
// ceiling 🤯.
const containSize = `min(var(--main-width), ${
dimensions.width
}px) min(calc(var(--main-width) * ${
dimensions.height / dimensions.width
}), ${dimensions.height}px)`;
img.setAttribute(
"style",
`background-size:cover;` +
`contain-intrinsic-size: ${containSize};` +
`background-image:url("${await blurryPlaceholder(src)}")`
);
const doc = img.ownerDocument;
const picture = doc.createElement("picture");
const avif = doc.createElement("source");
const webp = doc.createElement("source");
const jpeg = doc.createElement("source");
if (ACTIVATE_AVIF) {
await setSrcset(avif, src, "avif");
}
await setSrcset(avif, src, "avif");
avif.setAttribute("type", "image/avif");
await setSrcset(webp, src, "webp");
webp.setAttribute("type", "image/webp");
await setSrcset(jpeg, src, "jpeg");
const fallback = await setSrcset(jpeg, src, "jpeg");
jpeg.setAttribute("type", "image/jpeg");
if (ACTIVATE_AVIF) {
picture.appendChild(avif);
}
picture.appendChild(avif);
picture.appendChild(webp);
picture.appendChild(jpeg);
img.parentElement.replaceChild(picture, img);
picture.appendChild(img);
img.setAttribute("src", fallback);
} else if (!img.getAttribute("srcset")) {
await setSrcset(img, src, "jpeg");
const fallback = await setSrcset(img, src, "jpeg");
img.setAttribute("src", fallback);
}
};

async function setSrcset(img, src, format) {
img.setAttribute("srcset", await srcset(src, format));
const setInfo = await srcset(src, format);
img.setAttribute("srcset", setInfo.srcset);
img.setAttribute(
"sizes",
img.getAttribute("align")
? "(max-width: 608px) 50vw, 187px"
: "(max-width: 608px) 100vw, 608px"
);
return setInfo.fallback;
}

const dimImages = async (rawContent, outputPath) => {
Expand Down
7 changes: 5 additions & 2 deletions _11ty/optimize-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const csso = require("csso");

/**
* Inlines the CSS.
* Makes font display display-swap
* Makes font display display-optional
* Minifies and optimizes the JS
* Optimizes HTML
* Optimizes AMP
Expand All @@ -49,7 +49,10 @@ const purifyCss = async (rawContent, outputPath) => {
encoding: "utf-8",
});

before = before.replace(/@font-face {/g, "@font-face {font-display:swap;");
before = before.replace(
/@font-face {/g,
"@font-face {font-display:optional;"
);

const purged = await new PurgeCSS().purge({
content: [
Expand Down
Loading

0 comments on commit e359367

Please sign in to comment.