Giter Site home page Giter Site logo

presite's Introduction

presite

NPM version NPM downloads donate

Why Presite?

Presite is an alternative to static site generators like Gatsby, Next.js and Nuxt.js etc, the difference is that it uses Puppeteer to prerender websites instead of relying on server-side rendering.

Install

npm i -g presite

Note that Presite relies on Chrome (or Chromium) browser on your machine, so you need to ensure it's installed before running Presite.

Usage

presite ./path/to/your/site

Presite is supposed to work with existing single-page applications, first you use something like Create React App, Vue CLI, Parcel or Vite to create a production build of your app, then use Presite to pre-render the website to static HTML files.

Pre-rendered website will be generated into .presite folder.

Examples

with Create React App
{
  "scripts": {
-    "build": "react-scripts build"
+    "build": "react-scripts build && presite ./build"
  }
}
with Vue CLI
{
  "scripts": {
-    "build": "vue-cli-service build"
+    "build": "vue-cli-service build && presite ./dist"
  }
}
with Poi
{
  "scripts": {
-    "build": "poi build"
+    "build": "poi build && presite ./dist"
  }
}
with Vite
{
  "scripts": {
-    "build": "vite build"
+    "build": "vite build && presite ./dist"
  }
}

That's it, Presite prerender all pages of your website without any configuration!

Run presite --help for all CLI flags.

Non-HTML pages

Presite also supports rendering non-HTML pages like XML or JSON pages, simply create files ending with .xml.js or .json.js, let's say you have a feed.json.js:

import { createJSONFeed } from './somewhere/create-json-feed'

export default async () => {
  const posts = await fetch('/api/my-posts').then((res) => res.json())
  return createJSONFeed(posts)
}

You can export a function that resolves to a string or JSON object, then Presite will output this page as feed.json.

These pages are evaluated in browser in a <script type="module"> tag, so you can use the import keyword.

Using presite.config.js

Many CLI flags can be stored in a configuration file, it's totaly optional but if you need one, it's there for you.

Besides presite.config.js, you can also use presite.config.json or the presite key in package.json.

Set routes that needs prerender

If some of your pages are not referenced by other pages, you can manually specify them here:

module.exports = {
  routes: ['/', '/about'],
}

Note that in most cases you won't need this option, Presite automatically find all same-site <a> elements on the pages and prerender all of them.

If you want to fetch routes asynchronously, use async/await:

module.exports = {
  async routes() {
    const routes = await fetchRoutesFromSomeWhere()
    return routes
  },
}

Wait

Wait specific ms or dom element to appear:

module.exports = {
  wait: 3000,
  // Or wait for an element to appear
  // wait: '#comments'
}

Maunally set ready state

Instead of using wait you can manually tell when the app is ready:

module.exports = {
  manually: true,
}

Then you can call window.snapshot in your app when its contents are ready:

window.snapshot && window.snapshot()

To use a custom global variable name, set it to a string instead:

module.exports = {
  manually: `__my_snapshot__`,
}

Now you should call window.__my_snapshot__() instead.

Access Puppeteer browser page

Access the page instance, for example, to expose some functions from Node.js to browser:

module.exports = {
  async onBrowserPage(page) {
    await page.exposeFunction('md5', (content) => md5(content))
  },
}

Filter out link to be crawled

To prevent link (from <a> elements) to be crawled, you could use the linkFilter option:

module.exports = {
  // Returns `true` to keep, `false` otherwise
  linkFilter(url) {
    // Ignore URLs ending with .xml
    return !url.endsWith('.xml')
  },
}

Source directory

This is the same as using CLI presite ./path/to/your/spa:

module.exports = {
  baseDir: './path/to/your/spa',
}

Output directory

By default it outputs to .presite folder in current directory.

module.exports = {
  outDir: '.presite',
}

CLI options

Run presite --help.

Contributing

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

Author

presite © egoist, Released under the MIT License.
Authored and maintained by egoist with help from contributors (list).

Website · GitHub @egoist · Twitter @_egoistlily

presite's People

Contributors

alexisfontaine avatar dependabot-preview[bot] avatar dependabot[bot] avatar egoist avatar eth3lbert avatar michaelcurrin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

presite's Issues

Change workflow setup to control building and releasing better

Hi. I noticed that the CI workflow installs dependencies, runs tests (just an echo) and publishes to NPM. It does this on every commit and pull request to master.

https://github.com/egoist/presite/blob/master/.github/workflows/nodejs.yml

Can I suggest a few things?

Change publish style

Use a publish flow like this one from the docs.

https://docs.github.com/en/free-pro-team@latest/actions/guides/publishing-nodejs-packages#publishing-packages-using-yarn

It uses yarn publish instead of an external semantic-release package.

Publish conditionally

The CI run fails on my PR from my fork because I don't have access.

semantic-release cannot push the version tag to the branch master on the remote Git repository with URL https://x-access-token:[secure]@github.com/egoist/presite.git.\n' +

But also I shouldn't expect the publish to happen. Following the link from the previous section, you could rather publish to NPM only when a release is created in GitHub. Or perhaps just when a tag is created.

on:
  release:
    types: [created]

By the way, I also noticed release steps in package.json - I don't know if that is used as part of the CI or publishing from a local command line but they could be considered too.

https://github.com/egoist/presite/blob/master/package.json#L18

Add build step

Based on https://github.com/egoist/presite/blob/master/package.json#L15

It would be useful to add a step like this, which lets the CI tell you if your code is sound.

- name: Build app
  run: yarn build

This is useful both for development on a feature branch and also when actually publishing and if your yarn build fails then it can block publishing to NPM, which is a good idea to keep good quality of your releases.

Separate build and release flows

Some applications have two workflow files.

One workflow such as build.yml. It runs on all pushes to master and a feature branch. It will run tests and build the app and maybe lint or format, for code quality.

And another workflow like release.yml. It is only triggered on a release or tag created (not any commit). It will do the same steps as above, plus also publish to NPM.

It is also possible to do this in a single workflow with conditional statements, but two workflows is simpler and the duplication of steps is acceptable I think.

Let me know your thoughts.

Prerender Detection

Hello!

Is there any way for the app to tell whether it's being prerendered? I know that with react-snap you can check with navigator.userAgent === 'ReactSnap', so I'm wondering if there's an equivalent for this prerenderer.

I ask because I would like to add a few additional detection methods to the PR that I am going to be submitting on your vue-client-only component. I tested presite with vue-client-only, but unless I am missing something, it does not appear to work.

Thanks :)

How to run on Netlify?

First or all, thanks a lot for this awesome package!!
I'm trying to deploy to Netlify using presite but I keep receiving the error Error: Cannot find Chrome on your system.

I've tried already installing Netlify-plugin-chromium but with no success unfortunately.

Any idea how could I run presite on Netlify?

Presite does not run witith Jjavascript

I have tried to use ethe presite, however the result the error page with meessage "We're sorry but yourr-site.com doesn't work properly without JavaScript enabled. Please enable it to continue."

Any idea what I am doing wrong?

Update dependencies 😅

Hi
i think this node app is the best SPA pre-render solution because it's so easy to use and understand. No webpack required!

I'd love the dependencies to be updated! 😉

Failed to load resource: net::ERR_FAILED

Dear @egoist
I always get an error:

Failed to load resource: net::ERR_FAILED

for any content coming from my public folder and even CSS files.

> Executing task: npm run build <


> @cc/[email protected] build
> vue-tsc --noEmit && vite build && presite ./dist

vite v2.4.3 building for production...
✓ 11 modules transformed.
dist/index.html                  0.48kb
dist/assets/index.04023d7f.css   0.29kb / brotli: 0.16kb
dist/assets/index.b1778f7c.js    0.54kb / brotli: 0.37kb
dist/assets/vendor.69fd73e7.js   43.33kb / brotli: 15.67kb
Copy static assets
Crawling contents from http://localhost:54661/
Message from http://localhost:54661/assets/index.04023d7f.css:undefined:undefined Failed to load resource: net::ERR_FAILED
Message from http://localhost:54661/logo-wordmark.svg:undefined:undefined Failed to load resource: net::ERR_FAILED
Writing /index.html for /
Done, check out .presite folder

Terminal will be reused by tasks, press any key to close it.

Any idea why?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.