JavaScript API

You can use pree programmatically in Node.js or some compatible runtime. Locally install the package to get started:

npm i pree

There are three main functions exposed by pree that you can use:

🫕

serve() serves local files, handles layout, provides build-env APIs.

🏗️

build() calls serve(), then pre-renders HTML files and removes build-only scripts,

👀

view() calls serve() with live-reloading.


serve()

The core of pree is the serve() function. It will serve local files, handle metadata and layout and provide build-env APIs. It also provides a nice interface for navigating directories.

import { serve } from 'pree'

const { port, server } = await serve({ root: 'docs' })

Type signature & options:

function serve(options?: ServeOptions): Promise<RunningServer>
interface ServeOptions {
  // 📁 were should we look for files to serve. defaults to cwd.
  root?: string

  // 📍 base URL for your site.
  base?: string

  // 🔌 port to serve on. defaults to 3000.
  port?: number

  // 📦 loaders to use to load various files (see below).
  loaders?: Loader[]

  // 🚀 whether to serve in production mode (no env APIs). defaults to false.
  prod?: boolean

  // ✅ which files to inject build-env info into.
  include?: string[]

  // ❌ which files to exclude from build-env injection.
  exclude?: string[]

  // 🔗 base URL for build-env APIs. defaults to `@env`
  buildEnvPrefix?: string

  // 📣 log level:
  // 0: no logs (silent)
  // 1: errors only
  // 2: errors and warnings
  // 3: errors, warnings and info
  // 4: errors, warnings, info and debug
  logLevel?: number
}
type RunningServer = {
  port: number
  server: http.Server
  close: () => Promise<void>
}

Custom Loaders

Use custom loaders to change how specific file types are loaded. For example, you can use a markdown loader to convert .md files to HTML. This means your markdown files will be served as HTML, and they will be built into HTML files during build.

import { serve } from 'pree'
import { marked } from 'marked'

await serve({
  root: 'docs',
  loaders: [async (ctx, next) => {
    if (ctx.path.endsWith('.md')) {
      const raw = await readFile(ctx.path, 'utf8')

      return {
        content: marked(raw),
        type: 'text/html'
      }
    } else {
      return await next()
    }
  }]
})

build()

Calls serve(), then fetches all given HTML files with a headless browser and prebuilds them to given directory. Also removes all build-only scripts from the prebuilt files.

import { build } from 'pree'

await build({
  root: 'docs',
  dir: 'docs',
  target: 'site'
})

Type signature & options:

function build(options?: BuildOptions): Promise<void>
interface BuildOptions extends ServeOptions {
  // 📜 which file to build. either one of `file` or `dir` should be given.
  file?: string

  // 📁 which directory to build. either one of `file` or `dir` should be given.
  dir?: string

  // 🚚 where to put the built files. defaults to `dist`.
  target?: string

  // ✅ which files to build.
  include?: string[]

  // ❌ which files to exclude building.
  exclude?: string[]

  // 🔀 how many pages to build concurrently. defaults to 16.
  concurrency?: number
}

view()

Calls serve(), but also watches given files and automatically reloads the browser whenever there is a change. Takes the same options as serve().

import { view } from 'pree'

await view({ root: 'docs' })

Type signature & options:

function view(options?: ViewOptions): Promise<RunningViewer>
type ViewOptions = ServeOptions
type RunningViewer = RunningServer & {
  watcher: chokidar.FSWatcher
  ws: WebSocketServer
}

Proper Use Cases

Using the JavaScript API you can build various applications on top of pree. That said, pree is still built and optimized for a prebuilding a static collection of HTML files. It is NOT optimised for other use cases such as server-side rendering of dynamic content.

Specifically: pree prebuilds HTML files and speeds up loading by moving the wait time of the initial page load from client side to the build time. Based on the page, this can be pretty time consuming. In case of a fixed set of HTML files this overhead is resolved by prebuilding multiple pages concurrently. However that optimisation might not work in other contexts and use cases, so take that into consideration when you are using pree's APIs.



pree logo