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

signal-compiler

v0.1.2

Published

一种革命性的编译策略,用于构建基于 Signal 信号的响应式应用程序。

Readme

信号 Signal 编译器 English

一种革命性的编译策略,用于构建基于 Signal 信号的响应式应用程序。

让信号的开发接近无感,大幅增加可读性,同时享受无缝的 TypeScript 支持和卓越的开发者体验。

✨ 为什么选择信号编译器?

  • 零运行时开销:在构建时将普通 JavaScript 转换为细粒度响应式信号。
  • 直观 API:使用熟悉的 $ 前缀变量——无需学习新原语。
  • 信号传播:通过显式命名标记强制传递响应链,防止意外的非响应泄漏。
  • 框架无关:兼容 Babel、Vite 等工具。与 j20 或者 Preact Signal 等信号库完美搭配。
  • 类型安全:开箱即用的完整 TypeScript 类型推断。
  • 无混淆:信号与普通变量区分开,不会混淆。

告别冗长的信号包装器,迎接声明式响应性!

🚀 快速开始

安装

npm install signal-compiler

Babel 配置

babel.config.js 中添加插件:

import { signalCompiler } from "signal-compiler";

export default {
  plugins: [
    [
      signalCompiler,
      {
        importSource: "@preact/signals", // 指定信号模块(例如 '@preact/signals')
      },
    ],
  ],
};

Vite 配置

vite.config.js 中通过 Rollup 插件集成:

import { defineConfig } from "vite";
import { signalCompilerRollup } from "signal-compiler/rollup";

export default defineConfig({
  plugins: [
    signalCompilerRollup({
      include: "src/**/*.{js,jsx,ts,tsx}", // 目标文件/目录
      config: {
        importSource: "@preact/signals",
      },
    }),
  ],
});

运行您的构建( npm run buildvite dev ),您的 $ 前缀代码将神奇地变为响应式!

📖 核心编译策略

编译策略基于命名标记,使信号的使用像原生代码一样,让开发者编写更直观的代码;

编译器会从您指定的模块(例如 @preact/signals)自动注入 signal()computed()

核心概念

  1. 信号变量:以 $(非$use) 前缀的变量实际上为信号对象,用户无感,和普通变量一样使用。
  2. 信号读取:所有信号变量读取的时候都会自动解包,无需手动添加 .value,用户无感,和普通变量一样使用。
  3. 信号赋值:信号变量赋值时,会自动添加 .value,用户无感,和普通变量一样赋值即可。
  4. 信号传播:信号必须通过 $ 前缀变量(通常为派生信号,既 computed )传递才能保持响应性,否则变量值为原始信号对象,需要手动添加 .value 取值,在 Typescript 下值的类型和实际值不符。

编译规则

1、信号创建

使用 let 搭配 $ 前缀:

let $name = 1;
// 编译为:
import { signal } from "@preact/signals";
let $name = signal(1);

2、信号读取

自动追加 .value

let $name = 1;
console.log($name);
// 编译为:
let $name = signal(1);
console.log($name.value);

3、信号赋值

重定向到 .value

let $name = 1;
$name = 2;
console.log($name);
// 编译为:
let $name = signal(1);
$name.value = 2;
console.log($name.value);

4、信号派生

使用 const 搭配 $ 前缀:

let $name = 1;
const $displayName = $name + "a";
// 编译为:
import { signal, computed } from "@preact/signals";
let $name = signal(1);
const $displayName = computed(() => $name.value + "a");

5、自定义 Hook

函数名以 $use 前缀以实现响应性:

function $useName($age) {
  let $name = 1;
  return $name + $age;
}
let $age = 1;
const $name = $useName($age);
console.log($name);

// 编译为:
function $useName($age) {
  let $name = signal(1);
  // 1. 返回值包裹在 computed 中
  return computed(() => $name.value + $age.value);
}
let $age = signal(1);
// 2. 自定义 Hook 函数在使用时参数包裹在 computed 中
const $name = $useName(computed(() => $age.value));
console.log($name.value);

6、解构赋值

通过设置 $ 前缀的变量别名激活编译策略,以保持响应性:

// 输入参数为信号,name 变量需要使用 $ 前缀的别名传递,激活编译策略,以保留响应性。
function $useName({ name: $name }) {
  return {
    displayName: $name + "a",
  };
}

// 通过别名 $displayName 激活编译策略, 以保留响应性。
const { displayName: $displayName } = $useName({
  name: 1,
});
console.log($displayName);

// 编译为:
function $useName($__0) {
  // $__0 是临时变量,存储入参参数。
  const $name = computed(() => $__0.value.name);
  return computed(() => ({
    displayName: $name.value + "a",
  }));
}

const $__0 = $useName(
  computed(() => ({
    name: 1,
  }))
);
const $displayName = computed(() => $__0.value.displayName);
console.log($displayName.value);

信号传播

根据上述的编译策略,应该可以了解到,只有在 $ 前缀的变量中,才会被编译成信号。 所以,响应链的传递,是利用 $ 前缀的变量,通过显式标记的方式实现的。

信号的传递路径:

声明信号 -> 派生信号 -> hook(入参信号) -> hook(返回值信号) -> 派生/解构信号

这里每一步都会进行信号编译,响应才不会中断,这就是信号的传播机制。

📄 许可证

MIT