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

@jlchain/fe-pack

v1.1.0

Published

前端统一打包解决方案

Downloads

8

Readme

统一打包服务 fe-pack

一、npm工具

yarn add @jlchain/fe-pack 或者 npm install @jlchain/fe-pack

二、fe-pack的约定

  • typescript应用
  • react应用
  • 使用css(适合编写通用样式)、less(带有 css module,适合编写组件样式)、less(编译node_modules下的less文件,不带有css module,适合加载ant类型的组件)
  • [可配置修改] 默认入口文件为src/main.tsx
  • [可配置修改] 默认document.title 取值为 package.json中的description
  • [可配置修改] 默认端口号为8080
  • [可配置修改]webpack打包时解析别名(resolve.alias),与tsconfig.json中的compilerOptions.paths配置一致

三、fe-pack做了哪些事

1. 提供3个实用命令

  • 开发模式:fe-pack start

支持子命令:

  • --log 会输出所有请求信息
  • --disk 磁盘模式,会将编译结果输出到项目根目录下的dist文件夹中
  • --analyzer 分析模式,会分析编译结果,并以图形方式展现
  • 发布模式:fe-pack build

支持子命令:

  • --analyzer 分析模式,会分析编译结果,并以图形方式展现
  • 启动服务:fe-pack serve

2. 目前fe-pack已支持的能力

  • react应用

  • 资源服务

    • 访问日志
    • 资源压缩
    • 静态资源
    • 接口代理 proxy
    • 服务集群 cluster(仅生产模式)
  • 单入口打包

    • 开发编译、压缩编译、dll编译(方便的dll拆包能力)

    • 自动选取端口号避免端口占用问题

    • less 文件预编译

    • 自动定位浏览器页面

    • 远程访问开发环境(程序会自动获取当前主机ip地址,并在编译结束时显示在终端,方便告诉你的伙伴)

    • 开发模式接口代理 proxy

    • 支持插件plugins

    • 开发编译热重启

      // 开发编译监听的文件
      const watchList = [
        'feconfig.dev.js',
        'tsconfig.json',
        'package.json',
        'babel.config.js',
        '.babelrc',
      ];

3. fe-pack 的配置文件

所有的根配置都是可选的,你不配置,应用也能正常启动。

这些配置都是为了让应用具有更多的能力。

1) 开发配置

// feconfig.dev.js 很多时候会在开发环境修改,建议使用.gitignore,禁止提交git
interface IUserConf {
  // 应用标题,这个内容将会成为页面的tab名称、左侧菜单上面的应用标题栏内容,不配置时默认从package.json的description字段获取
  title?: string
  // 基准端口号,如果这个端口已被占用将自动选取其他空闲端口号,默认8080
  port?: number
  /**
   * 入口文件,默认为 main.tsx,无论入口文件命名如何,编译后的文件都是 main.js
   * fe-pack将会根据baseUrl和entryFile综合计算入口文件的完整路径
   * 单入口打包模式下,默认完整路径为 src/main.tsx
   */
  entryFile?: string
  /**
   * 项目入口文件根路径,默认为 src
   * fe-pack将会根据baseUrl和entryFile综合计算入口文件的完整路径
   * 单入口打包模式下,默认完整路径为 src/main.tsx
   */
  baseUrl?: string
  // 应用使用的mvvm框架: react(default) / vue,目前仅支持react
  mvvm?: 'react' | 'vue'
  // 打包模式: single(default): 单入口打包,multiple: 多入口打包,目前仅支持single
  mode?: 'single' | 'multiple'
  /**
   * 自定义插件
   */
  plugins?: ((context: IfeContext) => void)[]
}
/**
 * plugin可用的上下文api
 */
export interface IfeContext {
  /**
   * 获取当前node环境 dev / qa / pre / prod
   */
  getEnv: () => IEnvEnum
  /**
   * 获取命令行指令
   */
  getCommands: () => string[]
  /**
   * 获取配置内容,只读
   */
  getConfig: () => any
  /**
   * 注册命令
   * 仅支持
   * fe-pack start
   * fe-pack build
   * 下面的子命令
   * 比如 fe-pack start --log 中,--log就是使用 registCommand 注入的
   * fe-pack serve 暂时不支持注入命令
   */
  registCommand: (executor: () => [string, string] | Promise<[string, string]>) => void
  /**
   * 配置webpack的钩子,返回的json会自动合并到webpack配置中
   */
  configureWebpack: (executor: () => webpack.Configuration | Promise<webpack.Configuration>) => void
  /**
   * 编译前钩子
   */
  beforeCompile: (hook: () => void | Promise<void>) => void
  /**
   * 编译后钩子
   */
  afterCompile: (hook: () => void | Promise<void>) => void
  /**
   * 服务启动前的钩子,插件可以使用app注册任意中间件
   */
  beforeServer: (executor: (app: Express) => void | Promise<void>) => void
  /**
   * 服务监听端口后的钩子
   */
  afterServerListening: (hook: () => void | Promise<void>) => void
}
1.1)plugin插件系统

在fe-pack中,一个接受上下文并使用这个上下文进行扩展功能定义的函数,就是一个plugin。

这个plugin返回值必须是void,所以plugin不支持异步写法,但是所有的上下文钩子,都支持异步写法。

  • 内置plugin

fe-pack已经提供一些内置plugin,用来实现基本功能:

/**
 * 内置fe plugins
 */
export const plugins = [
  // 打包目标文件夹预删除功能
  predelPlugin,
  // 写入磁盘功能
  diskPlugin,
  // 打包分析功能
  analyzerPlugin,
  // 请求日志功能
  logPlugin,
  // less编译功能
  lessCompilePlugin,
  // 服务基础功能:(gzip/cookie/健康检查/静态资源服务/...)
  serverBasePlugin,
];

一个简单的内置plugin实现方式:

/**
 * 编译结果写入磁盘插件,根据--disk命令决定
 * 仅对开发模式生效,压缩模式固定写入磁盘
 * @param context
 * @returns
 */
export function diskPlugin(context: IfeContext) {
  const {
    getEnv, getCommands, registCommand, configureWebpack,
  } = context;
  const env = getEnv();
  if (env !== IEnvEnum.dev) return;
  registCommand(() => ['--disk', '磁盘模式,会将编译结果输出到项目根目录下的dist文件夹中']);
  const commands = getCommands();
  if (!commands.includes('--disk')) return;
  configureWebpack(() => ({
    devServer: {
      writeToDisk: true,
    },
  }));
}
  • 用户plugin

fe-pack 目前提供了2个用户plugin,来实现更高级的功能:

// 支持进行dll拆包
dllPlugin(option: IDllConfig | IDllConfig[])
// 支持自定义proxy代理
proxyPlugin(conf: IProxy | Record<IEnvEnum, IProxy>)

对于用户plugin,一个例子:

// feconfig.dev.js
module.exports = {

  // ...other configs

  plugins: [
    dllPlugin([
      {
        name: 'rbase',
        include: [
          'react',
          'react-dom',
        ],
      },
      {
        name: 'tools',
        include: 'moment',
      },
    ]),
    proxyPlugin({
      '/v1': {
        target: 'http://xxx.demo.com',
        changeOrigin: true,
        secure: false,
      },
    }),
  ],
};

由于plugin可能需要根据当前环境来决定具体行为,某些plugin可以使用如下的方式配置:

// feconfig.js
module.exports = {

  // ...other configs

  plugins: [
    proxyPlugin({
      qa: proxyconf('qa'),
      pre: proxyconf('pre'),
      prod: proxyconf('prod'),
    }),
  ],
};
  • 自定义plugin

如果上面所有内置plugin都无法满足你的项目需要,你可以编写自定义plugin,比如:

module.exports = {
  plugins: [
    (context) => {
      const {
        getEnv,
        getCommands,
        getConfig,
        registCommand,
        configureWebpack,
        beforeCompile,
        afterCompile,
        beforeServer,
        afterServerListening,
      } = context;
      // 判断当前环境
      const env = getEnv();
      const isDev = env === 'dev';
      // 注入monaco需要的语言
      configureWebpack(() => ({
        plugins: [
          new MonacoWebpackPlugin({
            languages: ['json', 'shell', 'python', 'java', 'javascript', 'typescript'],
          }),
        ],
      }));
      // 注册指令
      registCommand(() => ['--debug', '调试模式']);
      // 获取当前命令
      const commands = getCommands();
      // 判断是否是调试模式
      const isDebug = commands.includes('--debug');
      // 添加服务中间件
      beforeServer((app) => {
        app.use((req, res) => {
          // todo something
        });
      });
    },
  ],
};

2) tsconfig.json

对于fe-pack来说tsconfig.json文件是必须的,这意味着你的应用必须是一个ts应用

fe-pack会根据你的ts配置中的 compilerOptions.paths 配置自动生成 webpack alias 别名

不配置将不会生成别名

3) package.json

fe-pack会观察package.json中的一些配置,来确定具体行为:

  • description : 应用描述,用户如果没有在 feconfig.js 配置 title ,fe-pack会降级使用description
  • dependencies : fe-pack会根据你的依赖包,自动确定应用使用的mvvm框架,所以你可以不配置mvvm属性

4) babel.config.js 或者 .bablerc

fe-pack 支持babel零配置

fe-pack 会观察 babel配置,来确定具体行为

如果用户配置了babel,fe-pack会将用户配置与默认配置合并

如果用户不配置babel,fe-pack会降级使用默认配置,默认配置如下:

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        useBuiltIns: 'usage',
        corejs: 3,
      },
    ],
    '@babel/preset-typescript',
    '@babel/preset-react',
  ],
  plugins: [
    '@babel/plugin-transform-runtime',
  ],
  env: {
    dev: {
      plugins: [
        ['react-refresh/babel', { skipEnvCheck: true }],
      ],
    },
  },
};

该默认配置决定了应用必须是react,并没有指定更多定制化场景,比如你如果想要使用antd,你的.babelrc可以配置如下:

{
  "plugins": [
    ["babel-plugin-import", {
      "libraryName": "antd",
      "style": true
    }, "antd"], // 如果你想要使用antd
    ["@babel/plugin-proposal-decorators", { "legacy": true }] // 如果你想要使用decorator
  ]
}

4. 你还需要在应用中配置哪些内容

  • package.json

    {
      //...
      "scripts": {
        "start": "fe-pack start",
        "build": "fe-pack build",
        "serve": "fe-pack serve"
      },
      //...
    }
  • .gitignore

    # ...
    feconfig.dev.js
  • .eslintrc.js 推荐使用@jlchain/fe-lint-react

  • .stylelintrc.js 推荐使用@jlchain/fe-lint-react包下的@jlchain/fe-lint-react/stylelint