Milan Felix Šulc
📦 Package maker • 👷 Architect ModernTV • 🐘 PHP enthusiast • 💿 Multimedia engineer • 👨👩👧👦 Father • ☕️ Coffee-based
How To Develop
Custom Vercel Runtime
01.10.2020
@xf3l1x
f3l1x.io
site
└── index.html$ vercel$ vercel
Vercel CLI 20.1.1
? Set up and deploy “~/2020-10-01-vercel-meetup/01-zero-config”? [Y/n] y
? Which scope do you want to deploy to? xorg
? Link to existing project? [y/N] n
? What’s your project’s name? 01-zero-config
? In which directory is your code located? ./
No framework detected. Default Project Settings:
- Build Command: `npm run vercel-build` or `npm run build`
- Output Directory: `public` if it exists, or `.`
- Development Command: None
? Want to override the settings? [y/N] n
🔗  Linked to xorg/01-zero-config (created .vercel and added it to .gitignore)
🔍  Inspect: https://vercel.com/xorg/01-zero-config/lvnj9dd0a [1s]
✅  Production: https://01-zero-config.vercel.app [copied to clipboard] [8s]
📝  Deployed to production. Run `vercel --prod` to overwrite later (https://vercel.link/2F).
💡  To change the domain or build command, go to https://vercel.com/xorg/01-zero-config/settingssite
└── index.html$ vercel$ vercel
Vercel CLI 20.1.1
? Set up and deploy “~/2020-10-01-vercel-meetup/01-zero-config”? [Y/n] y
? Which scope do you want to deploy to? xorg
? Link to existing project? [y/N] n
? What’s your project’s name? 01-zero-config
? In which directory is your code located? ./
No framework detected. Default Project Settings:
- Build Command: `npm run vercel-build` or `npm run build`
- Output Directory: `public` if it exists, or `.`
- Development Command: None
? Want to override the settings? [y/N] n
🔗  Linked to xorg/01-zero-config (created .vercel and added it to .gitignore)
🔍  Inspect: https://vercel.com/xorg/01-zero-config/lvnj9dd0a [1s]
✅  Production: https://01-zero-config.vercel.app [copied to clipboard] [8s]
📝  Deployed to production. Run `vercel --prod` to overwrite later (https://vercel.link/2F).
💡  To change the domain or build command, go to https://vercel.com/xorg/01-zero-config/settingssite
└── index.html$ vercel$ vercel
Vercel CLI 20.1.1
? Set up and deploy “~/2020-10-01-vercel-meetup/01-zero-config”? [Y/n] y
? Which scope do you want to deploy to? xorg
? Link to existing project? [y/N] n
? What’s your project’s name? 01-zero-config
? In which directory is your code located? ./
No framework detected. Default Project Settings:
- Build Command: `npm run vercel-build` or `npm run build`
- Output Directory: `public` if it exists, or `.`
- Development Command: None
? Want to override the settings? [y/N] n
🔗  Linked to xorg/01-zero-config (created .vercel and added it to .gitignore)
🔍  Inspect: https://vercel.com/xorg/01-zero-config/lvnj9dd0a [1s]
✅  Production: https://01-zero-config.vercel.app [copied to clipboard] [8s]
📝  Deployed to production. Run `vercel --prod` to overwrite later (https://vercel.link/2F).
💡  To change the domain or build command, go to https://vercel.com/xorg/01-zero-config/settingssite
└── index.html$ vercel$ vercel
Vercel CLI 20.1.1
? Set up and deploy “~/2020-10-01-vercel-meetup/01-zero-config”? [Y/n] y
? Which scope do you want to deploy to? xorg
? Link to existing project? [y/N] n
? What’s your project’s name? 01-zero-config
? In which directory is your code located? ./
No framework detected. Default Project Settings:
- Build Command: `npm run vercel-build` or `npm run build`
- Output Directory: `public` if it exists, or `.`
- Development Command: None
? Want to override the settings? [y/N] n
🔗  Linked to xorg/01-zero-config (created .vercel and added it to .gitignore)
🔍  Inspect: https://vercel.com/xorg/01-zero-config/lvnj9dd0a [1s]
✅  Production: https://01-zero-config.vercel.app [copied to clipboard] [8s]
📝  Deployed to production. Run `vercel --prod` to overwrite later (https://vercel.link/2F).
💡  To change the domain or build command, go to https://vercel.com/xorg/01-zero-config/settingssite
├── index.html
├── index.php
├── package.json
└── vercel.json$ vercel{
    "builds": [
        { "src": "index.html", "use": "@vercel/static" },
        { "src": "package.json", "use": "@vercel/static-build" },
        { "src": "index.php", "use": "vercel-php" }
    ]
}{ CODE }
{ CODE }
▲ RUNTIME
▲ BUILD PHASE
site
├── index.html
├── index.php
├── package.json
└── vercel.json{
    "builds": [{
        "src": "index.html",
        "use": "@vercel/static"
    }]
}$ vercel
builder1.build(ctx)
index.html dist/main.css dist/app.js
/api/users /api/comments
STATIC FILES
LAMBDAS
builderN.build(ctx)
Builders
@vercel/static
@vercel/static-build
@vercel/node
@vercel/go
@vercel/python
@vercel/ruby
officials
community
vercel-bash
vercel-deno
vercel-php
now-rust
vercel-sapper
@nuxtjs/vercel-builder
Builders
@vercel/static
@vercel/static-build
@vercel/node
@vercel/go
@vercel/python
@vercel/ruby
officials
community
vercel-bash
vercel-deno
vercel-php
now-rust
vercel-sapper
@nuxtjs/vercel-builder
MD → HTML
new stuff
challenge
learn sth
have fun
interface Runtime {
  version: number;
  
  build: (options: BuildOptions) => Promise<BuildResult>;
  
  analyze?: (options: AnalyzeOptions) => Promise<string>;
  
  prepareCache?: (options: PrepareCacheOptions) => Promise<CacheOutputs>;
  
  shouldServe?: (options: ShouldServeOptions) => Promise<boolean>;
  
  startDevServer?: (
    options: StartDevServerOptions
  ) => Promise<StartDevServerResult>;
}interface Runtime {
  
  build: (options: BuildOptions) => Promise<BuildResult>;
  
}[file structure]
runtime
├── src
│   └── index.ts
├── package.json
├── tsconfig.json
└── README.md[package.json]
{
  "name": "vercel-md",
  "description": "Markdown Runtime for Vercel platform",
  "version": "0.0.1",
  "license": "MIT",
  "main": "./dist/index.js",
  "files": [
    "dist"
  ],
  "dependencies": {
    "markdown-it": "^11.0.1"
  },
  "devDependencies": {
    "@types/node": "^14.0.14",
    "@vercel/build-utils": "^2.4.0",
    "typescript": "^4.0.2"
  }
}
[src/index.ts]
import { BuildOptions } from "@vercel/build-utils";
export async function build(options: BuildOptions): Promise<any> {
  
  console.log(options);
};
site
├── index.md
└── vercel.json[src/index.ts]
import { FileBlob, BuildOptions } from "@vercel/build-utils";
import markdownit from 'markdown-it';
export async function build({ files, entrypoint }: BuildOptions): Promise<any> {
  const file = await FileBlob.fromStream({
    stream: files[entrypoint].toStream(),
  });
  const md = new markdownit();
  const result = new FileBlob({
    data: md.render(file.data.toString())
  });
  const replacedEntrypoint = entrypoint.replace(/\.[^.]+$/, '.html');
  return { [replacedEntrypoint]: result };
};
[src/index.ts]
import { FileBlob, BuildOptions } from "@vercel/build-utils";
import markdownit from 'markdown-it';
export async function build({ files, entrypoint }: BuildOptions): Promise<any> {
  const file = await FileBlob.fromStream({
    stream: files[entrypoint].toStream(),
  });
  const md = new markdownit();
  const result = new FileBlob({
    data: md.render(file.data.toString())
  });
  const replacedEntrypoint = entrypoint.replace(/\.[^.]+$/, '.html');
  return { [replacedEntrypoint]: result };
};
[src/index.ts]
import { FileBlob, BuildOptions } from "@vercel/build-utils";
import markdownit from 'markdown-it';
export async function build({ files, entrypoint }: BuildOptions): Promise<any> {
  const file = await FileBlob.fromStream({
    stream: files[entrypoint].toStream(),
  });
  const md = new markdownit();
  const result = new FileBlob({
    data: md.render(file.data.toString())
  });
  const replacedEntrypoint = entrypoint.replace(/\.[^.]+$/, '.html');
  return { [replacedEntrypoint]: result };
};
import { FileBlob, BuildOptions } from "@vercel/build-utils";
import markdownit from 'markdown-it';
export async function build({ files, entrypoint }: BuildOptions): Promise<any> {
  const file = await FileBlob.fromStream({
    stream: files[entrypoint].toStream(),
  });
  const md = new markdownit();
  const result = new FileBlob({
    data: md.render(file.data.toString())
  });
  const replacedEntrypoint = entrypoint.replace(/\.[^.]+$/, '.html');
  return { [replacedEntrypoint]: result };
};
index.md → index.html
[src/index.ts]
[src/index.ts]
import { FileBlob, BuildOptions } from "@vercel/build-utils";
import markdownit from 'markdown-it';
export async function build({ files, entrypoint }: BuildOptions): Promise<any> {
  const file = await FileBlob.fromStream({
    stream: files[entrypoint].toStream(),
  });
  const md = new markdownit();
  const result = new FileBlob({
    data: md.render(file.data.toString())
  });
  const replacedEntrypoint = entrypoint.replace(/\.[^.]+$/, '.html');
  return { [replacedEntrypoint]: result };
};
[publishing]
npm publish
{
    "builds": [
        { "src": "*.md", "use": "vercel-md" }
    ]
}
speedup workflow
take challenges
explore & conquer
have fun
@xf3l1x
f3l1x.io
By Milan Felix Šulc
📦 Package maker • 👷 Architect ModernTV • 🐘 PHP enthusiast • 💿 Multimedia engineer • 👨👩👧👦 Father • ☕️ Coffee-based