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 🙏

© 2024 – Pkg Stats / Ryan Hefner

babel-plugin-label-switch

v1.0.0

Published

a babel plugin to select to remove some label code

Downloads

2

Readme

babel-plugin-label-switch

一个根据labeled statement 标记语句的标识符进行选择性输出的插件。

适用场景: ** 单文件/单项目书写多平台代码,针对特定平台,在保留该平台代码的同时移除其他平台代码。**

参数

  • prefix:一个用于识别标识符前缀的正则表达式。为了防止作用到其他标识语句,必须使用特定前缀区分,默认的前缀是case$_*
    • type: RegExp
    • default: /^case\$_/
  • map:一个标识符的映射表,用来决定哪些标记语句需要被移除。若某个标记语句的标识符存在该表里面,且其值为true,则保留标记语句的内容。否则整体移除
    • type: Object
    • default: {}

例子

  • babel 配置:
{
	"plugins": [
		[
			"babel-plugin-label-switch",
			{
				"prefix": /^myPrefix_/,
				"map": {
					"isNode": false,
					"isBrowser": true,
					"isWxProgram": false
				}
			}
		]
	]
}
  • 在 js 里面使用上述的标识符:
function request(method, url) {
	return new Promise((resolve, reject) => {
		myPrefix_isNode: {
			//node环境发起请求
			require('http')
				.request(
					url,
					{
						method
					},
					function() {
						resolve();
					}
				)
				.end();
		}

		myPrefix_isBrowser: {
			//浏览器环境发起请求
			var xhr = new XMLHttpRequest();
			xhr.open(method, url);
			xhr.onload = function() {
				resolve();
			};
			xhr.send();
		}

		myPrefix_isWxProgram: {
			//小程序环境发起请求
			wx.request({
				url,
				method,
				success: function() {
					resolve();
				}
			});
		}
	});
}
  • 经过 babel 转换后:
function request(method, url) {
	return new Promise((resolve, reject) => {
		var xhr = new XMLHttpRequest();
		xhr.open(method, url);
		xhr.onload = function() {
			resolve();
		};
		xhr.send();
	});
}

注意事项

不要对插件作用的标识语句使用 break/continue

不管当前代码块是保留还是移除,其标识符总会被移除,实际上标识符与其标识语句并不存在于 js 的运行时中,在编译阶段会被移除。

//bad
case$_isNode: for (let i = 0; i < 9; i++) {
	loop: for (let j = 0; j < 9; j++) {
		if (i == 1 && j == 1) {
			continue case$_isNode;
		}
	}
}

//good
case$_isNode: {
	loop1: for (let i = 0; i < 9; i++) {
		loop2: for (let j = 0; j < 9; j++) {
			if (i == 1 && j == 1) {
				continue loop1;
			}
		}
	}
}

作用域问题

  • 局部作用域变量 如果采用了形如label:{ statement }的标记语法,则需要注意一下作用域问题。代码经过插件转换后,会移除掉标记语法。若标记语法所标记内容存在let/const局部作用域变量,则需要谨慎检查这些变量是否与其他变量同名。

    const a = 10;
    case$_isNode: {
    	let a = 20;
    	console.log(a);
    }
        
    // ===>转换后:
    const a = 10;
    let a = 20; //<====Error!!!!
    console.log(a);
  • import 问题 js 语法规定,import必须在最外层的作用域里面执行,如果需要动态选择引入的文件,请使用require

  • export 问题 js 语法规定,export必须在最外层的作用域里面执行,因此,需要一些小小的技巧来规避这个问题

    export default (function() {
    	case$_isNode: {
    		let a = 20;
    		return a;
    	}
    	case$_isBrowser: {
    		let a = 20;
    		return a;
    	}
    })();

在 typescript 中使用

在 ts 中的使用与 js 类型,需要注意的是,ts 的引入与 js 有些许不同:

import * as React from 'react';
import * as TReactDOM from 'react-dom';
import * as TReactDOMServer from 'react-dom/server/';
import App from './app';
export default (function(){
	case$_isBrowser:{
		const ReactDOM:typeof TReactDOM=require('react-dom');
		ReactDOM.render(<App/>,document.getElementById("app"));
	}
	
	case$_isNode:{
		const ReactDOMServer:typeof TReactDOMServer=require('react-dom/server/');
		const str = ReactDOMServer.renderToString(<App/>);
		return str
	}
})();

在上述代码中,TReactDOMTReactDOMServer分别来自@types/react-dom@types/react-dom/server/,仅仅是引入typescript的类型文件。真正的引入来自于require语句,这样既保留了ts的类型,也实现了动态引入。