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.
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.
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.
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.
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.
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
.
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 specific ms or dom element to appear:
module.exports = {
wait: 3000,
// Or wait for an element to appear
// wait: '#comments'
}
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 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))
},
}
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')
},
}
This is the same as using CLI presite ./path/to/your/spa
:
module.exports = {
baseDir: './path/to/your/spa',
}
By default it outputs to .presite
folder in current directory.
module.exports = {
outDir: '.presite',
}
Run presite --help
.
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request :D
presite © egoist, Released under the MIT License.
Authored and maintained by egoist with help from contributors (list).
Website · GitHub @egoist · Twitter @_egoistlily