JSPM一个前端神器,配合esbuild wasm可以在页面打包任何想要在浏览器端运行的依赖包

06-01 1339阅读

需求背景

有时候想打包一些库,直接能在浏览器端运行,如果用rollup这种工具打包,很多node端的依赖无法解决。比如像postcss严重依赖node path fs 等等模块,但你想在浏览器执行css解析想运行postcss。那么jspm出现了,根据在它网站添加你想要运行的库,会自动生成importmap.有了这个我们就可以在浏览器esm模式引用导入了.

接下来正是利用jspm的优势,直接用esbuild 利用fetch从jspm导入依赖。就直接能打包了。下面详细讲绍写的插件

如:

JSPM一个前端神器,配合esbuild wasm可以在页面打包任何想要在浏览器端运行的依赖包

ESBuild Wasm

完成打包任务依赖几下:

  • jspm生成的importmap
  • esbuild-wasm
  • es-module-shims 的importmap解析器
  • esbuild 自定义esmPlugin

    执行流程就是

    • 配置esbuld config
    • 添加esmPlugin插件 传入entryCode 和importmap(jspm生成的)
    • 执行esbuild.build方法就ok.最后把contents 转换成blob 下载

      esbuild wasm版本是可以在浏览器端运行的,我之前通过这个写了一个指向em.sh网站的前端无安装快速打包工具.

       function EsmPlugin({ entryCode, importmap }) {
                  return {
                      name: 'esm-bundle',
                      /**
                       * @params {import('../../scripts/backstage/esbuild/lib/browser.d.ts').PluginBuild} build
                       */
                      setup: (build) => {
                      // 这个createImportMapResolver解析是来自:es-module-shims
                          const resolver = esmResolver.createImportMapResolver(importmap)
         
                          build.onResolve({ filter: /.*/ }, args => {
                              const { path, importer, namespace, resolveDir, kind, pluginData } = args
              
                              if (kind === 'entry-point') {
                                  return {
                                      namespace: 'local-module',
                                      pluginData: {
                                          content: entryCode
                                      },
                                      path
                                  }
                              }
                              const realPath = resolver(path,importer)
                              return {
                                  path: realPath,
                                  pluginData,
                                  namespace:'http-module'
                              }
                          })
                          // 加载远程
                          build.onLoad({ filter: /.*/, namespace: 'http-module' }, async (args) => {
                              const { path, namespace, suffix, pluginData } = args
                              const content=await fetch(path).then(res=>res.clone()).then(res=>res.text()).catch(()=>'// 错误')
                              return {
                                  contents:content
                              }
                          })
                          // 加载
                          build.onLoad({ filter: /.*/, namespace: 'local-module' }, (args) => {
                              const { path, namespace, suffix, pluginData } = args
                              return {
                                  contents: pluginData.content
                              }
                          })
                      }
                  }
              }
              function initializeBuild() {
                  esbuild.build({
                      entryPoints: {
                          main: 'index.js'
                      },
                      target: 'es2015',
                      format: 'iife',
                      bundle: true,
                      platform: "browser",
                      define: {
                      },
                      plugins: [EsmPlugin({
                          entryCode: `
                          export * from 'postcss'
                          `,
                          importmap: {
                              "imports": {
                                  "postcss": "https://ga.jspm.io/npm:postcss@8.5.3/lib/dev.postcss.mjs"
                              },
                              "scopes": {
                                  "https://ga.jspm.io/": {
                                      "buffer": "https://ga.jspm.io/npm:@jspm/core@2.1.0/nodelibs/browser/buffer.js",
                                      "fs": "https://ga.jspm.io/npm:@jspm/core@2.1.0/nodelibs/browser/fs.js",
                                      "nanoid/non-secure": "https://ga.jspm.io/npm:nanoid@3.3.11/non-secure/index.js",
                                      "path": "https://ga.jspm.io/npm:@jspm/core@2.1.0/nodelibs/browser/path.js",
                                      "picocolors": "https://ga.jspm.io/npm:picocolors@1.1.1/picocolors.browser.js",
                                      "process": "https://ga.jspm.io/npm:@jspm/core@2.1.0/nodelibs/browser/process.js",
                                      "source-map-js": "https://ga.jspm.io/npm:source-map-js@1.2.1/source-map.js",
                                      "url": "https://ga.jspm.io/npm:@jspm/core@2.1.0/nodelibs/browser/url.js"
                                  },
                                  "https://ga.jspm.io/npm:postcss@8.5.3/lib/dev.no-work-result.js": {
                                      "nanoid/non-secure": "https://ga.jspm.io/npm:nanoid@3.3.11/non-secure/index.cjs"
                                  },
                                  "https://ga.jspm.io/npm:postcss@8.5.3/lib/dev.parse.js": {
                                      "nanoid/non-secure": "https://ga.jspm.io/npm:nanoid@3.3.11/non-secure/index.cjs"
                                  },
                                  "https://ga.jspm.io/npm:postcss@8.5.3/lib/dev.postcss.js": {
                                      "nanoid/non-secure": "https://ga.jspm.io/npm:nanoid@3.3.11/non-secure/index.cjs"
                                  },
                                  "https://ga.jspm.io/npm:postcss@8.5.3/lib/dev.processor.js": {
                                      "nanoid/non-secure": "https://ga.jspm.io/npm:nanoid@3.3.11/non-secure/index.cjs"
                                  },
                                  "https://ga.jspm.io/npm:postcss@8.5.3/lib/fromJSON.js": {
                                      "nanoid/non-secure": "https://ga.jspm.io/npm:nanoid@3.3.11/non-secure/index.cjs"
                                  },
                                  "https://ga.jspm.io/npm:postcss@8.5.3/lib/input.js": {
                                      "nanoid/non-secure": "https://ga.jspm.io/npm:nanoid@3.3.11/non-secure/index.cjs"
                                  },
                                  "https://ga.jspm.io/npm:postcss@8.5.3/lib/map-generator.js": {
                                      "nanoid/non-secure": "https://ga.jspm.io/npm:nanoid@3.3.11/non-secure/index.cjs"
                                  }
                              }
                          }
                      })],
                      external: [],
                      globalName: "MyLib",
                      outdir: "./dist"
                  }).then((result) => {
                      console.log('complete', result)
                      const outputFiles=result.outputFiles
                      if(outputFiles.length>0){
                          downLoadFile(outputFiles[0].path,new Blob([
                               outputFiles[0].contents
                          ],{
                              type:'text/js'
                          }))
                      }
                      //return result.outputFiles.length ? result.outputFiles[0].text : ''
                  })
              }
      

      📦 JSPM 全面解析 — 下一代浏览器原生模块化解决方案


      🎯 什么是 JSPM?

      JSPM,全称 JavaScript Package Manager,最初是一个类似于 NPM + Webpack 的前端模块化打包工具。

      随着 Web 标准的发展,它逐渐转型为基于 ESM(ECMAScript Modules) 和 importmap 的现代浏览器模块加载解决方案,让前端项目可以:

      • 摆脱打包器
      • 不依赖 node_modules
      • 直接用 CDN 加载标准 ESM
      • 支持多版本、按作用域映射依赖

        📌 简单说:它让你像后端一样用原生模块,像 Deno 一样不用打包,像微前端一样可以自由控制版本。


        🌐 JSPM 核心组成

        组件作用
        jspm.dev免费 ESM CDN,托管 npm 包的 ESM 版本
        SystemJS模块加载器,兼容 ESM、CJS、AMD(早期核心)
        importmap.dev在线 importmap 配置和托管服务
        JSPM Generator动态生成 importmap 的工具库

        📦 jspm.dev — 现代浏览器 ESM CDN

        这是现在 JSPM 生态的核心:

        • 每个 npm 包都托管为纯标准 ESM
        • 支持 importmap,方便统一版本和路径映射
        • 不挂载 global,不 polyfill Node API,100% 原生 ESM

          示例:

          import React from "https://jspm.dev/react@18"
          import _ from "https://jspm.dev/lodash@4.17.21"
          

          特点:

          • 📖 URL 唯一即版本唯一(支持 semver 范围)
          • 🚀 无打包,直接上生产
          • 🔒 CDN 静态缓存,长期稳定

            📖 importmap — 依赖映射核心

            JSPM 主打和浏览器 importmap 配合,解决模块裸导入的问题。

            {
              "imports": {
                "vue": "https://jspm.dev/vue@3",
                "lodash": "https://jspm.dev/lodash@4.17.21"
              },
              "scopes": {
                "https://example.com/admin/": {
                  "vue": "https://jspm.dev/vue@2.7"
                }
              }
            }
            
            • imports 👉 全局依赖映射
            • scopes 👉 某路径下专属依赖版本(多版本共存)

              🛠️ JSPM Generator

              一个 NPM 包 + 在线服务,可以:

              • 自动生成 importmap
              • 解析 npm 依赖树
              • 输出版本锁定的 CDN 地址

                👉 https://generator.jspm.io/

                示例:

                import { install } from '@jspm/generator'
                const generator = new install()
                await generator.install('vue')
                console.log(generator.importMap)
                

                🎨 JSPM 能做什么?

                场景优势
                无打包部署静态 HTML + importmap,零构建上线
                微前端多版本依赖scopes 多版本隔离,互不干扰
                线上 demo / 原型开发直接 CDN 引入,热更快
                Deno / Bun 跨平台项目同样走 ESM CDN,统一 URL 化
                向后兼容改造旧项目不动 webpack,静态页面分阶段升级

                📊 和其它 ESM CDN 对比

                特性jspm.devesm.shskypack.dev
                构建方式自研纯 ESM 构建esbuild 转 ESMesbuild + polyfill
                importmap 支持✅ 强配套
                CJS 兼容方式转标准 ESM,不挂 global、不 polyfillshim process、Buffer 等shim、polyfill 多
                多版本隔离✅ scopes + importmapURL 隔离URL 隔离
                微前端友好度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

                👉 最适合 无打包 + 微前端 + 纯 ESM 场景的,就是 jspm.dev。


                📚 JSPM 和前端未来

                JSPM 其实是浏览器原生模块化标准化的先锋实践者,它做的事情,正是:

                • 用 URL 做依赖
                • 用 importmap 映射版本
                • 用 ESM 标准化所有库
                • 不用 Node 环境

                  未来 Deno、Bun、浏览器本地项目都会往这方向靠近。

                  JSPM 正是Vite / Deno / Bun 模块化生态里的 CDN 版排头兵。


                  ✅ 总结

                  JSPM 是…意义
                  ESM CDN纯浏览器端 CDN,托管 npm ESM 版本
                  importmap 配套方案控制依赖版本、作用域、URL 映射
                  微前端好搭档scopes 多版本共存
                  打包器替代无需 node_modules 和 Webpack/Vite
                  未来标准推动者向标准 ESM + URL 化过渡

                  如果你需要,我可以帮你把这份内容排成更漂亮的 markdown、Notion 样式或者直接写个博客开头、目录、结尾都写好。要不要我帮你整理一下?✨

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码