npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jl-org/ssg

v0.0.3

Published

一键把单页应用转换成静态网站

Readme

一键把单页应用转换成静态网站

支持任何前端框架,如 React、Vue、Angular、Svelte 等

安装

npm i @jl-org/ssg puppeteer-core -D

快速上手

  1. 生成静态 HTML scripts/ssg.cjs
const path = require('node:path')
const { ssg } = require('@jl-org/ssg')
const puppeteer = require('puppeteer-core')


const PORT = '4173'
main()

async function main() {
  await ssg({
    port: PORT,
    /**
     * 创建浏览器实例的函数,默认需要你自行下载 puppeteer-core 或者 puppeteer
     * ### 因为 puppeteer 会自动下载浏览器,所以提供此配置。你可以使用自己浏览器的路径,节省内存
     * @example
     * puppeteer.launch({ headless: true, ... })
     */
    createBrowser: () => puppeteer.launch({
      executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe',
      headless: true
    }),
    ssgPages: [
      {
        url: `http://localhost:${PORT}`,
        target: path.resolve(__dirname, '../dist/index.html')
      },
      {
        url: `http://localhost:${PORT}/pricing`,
        target: path.resolve(__dirname, '../dist/pricing.html')
      },
      {
        url: `http://localhost:${PORT}/about`,
        target: path.resolve(__dirname, '../dist/about.html')
      },
    ]
  })

  process.exit(0)
}
  1. 修改 Nginx 配置,并且重启服务
server {
  listen 80;
  server_name yourdomain.com;

  # pages
  location /pricing {
    root /Your_Root_Dir;
    index pricing.html;
    try_files $uri $uri/ /pricing.html;
  }
  location /about {
    root /Your_Root_Dir;
    index about.html;
    try_files $uri $uri/ /about.html;
  }
}
  1. 测试生效
# 查看返回内容,是否为整个 HTML
curl http://yourdomain.com/pricing

配置项


export interface SSGOptions {
  ssgPages: SSGPage[]

  /**
   * 启动服务器的端口
   * @default '4173'
   */
  port?: string
  /**
   * spawn 启动服务器的命令的第一个参数
   * @default 'npx'
   */
  startServerCmd?: string
  /**
   * spawn 启动服务器的命令的参数列表
   * @default 
   * ['vite', 'preview', '--port', PORT]
   */
  startServerArgs?: readonly string[]

  /**
   * 是否需要压缩 HTML 文件
   * @default true
   */
  needMinify?: boolean
  /**
   * 压缩 HTML 文件的配置
   * @default
   * {
   *   collapseWhitespace: true, // 删除多余的空格
   *   removeComments: true, // 删除注释
   *   removeAttributeQuotes: false, // 删除属性的引号(当安全时)
   *   minifyCSS: true, // 压缩内联 CSS
   *   minifyJS: true, // 压缩内联 JS
   * }
   */
  minifyOptions?: Options

  /**
   * 创建浏览器实例的函数,默认需要你自行下载 puppeteer-core 或者 puppeteer
   * ### 因为 puppeteer 会自动下载浏览器,所以提供此配置。你可以使用自己浏览器的路径,节省内存
   * @example
   * await puppeteer.launch({ headless: true, ... })
   */
  createBrowser: () => Promise<Browser>
  /**
   * 页面打开前的回调函数,可以用来设置一些页面的配置
   */
  onBeforeOpenPage?: (page: Page) => Promise<void>
}

原理

  • 项目打包后有一个 dist 文件夹,此脚本会启动一个本地服务器,默认用 vite preview 来查看
  • 然后调用 puppeteer 模拟打开浏览器,访问每个页面,生成静态 HTML 文件
  • 最后将生成的 HTML 文件放到指定目录,并替换掉原来的 HTML 文件