使用Rollup解析从URL导入的ES6模块

6

在ES6模块中从URL导入是完全有效的,因此我一直使用这种技术在不同主机/端口的微服务之间重用模块:

import { authInstance } from "http://auth-microservice/js/authInstance.js"

我正在进行发布周期,并已开始使用rollup将代码打包为IIFEs。但是,Rollup似乎不支持从URL导入es6模块,我认为它应该支持,因为这在规范中是允许的 :(

module-name 要导入的模块。这通常是一个相对或绝对路径名称,指向包含模块的.js文件。某些捆绑器可能允许或需要使用扩展名,请检查您的环境。只允许单引号和双引号字符串。(参考链接:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)

我已经在网络上搜索了一个小时,但没有找到类似于rollup-plugin-node-resolve的解析程序,可以用于解析来自URL的模块。有人看到过吗?

2个回答

5

我必须迅速地离开这个问题,所以只写了一个 rollup 插件的框架。我仍然认为解析绝对路径应该成为 rollup 的核心功能。

更新片段

我们已经使用这个工具转换生产环境代码了相当长的一段时间,包括我们几个应用程序的代码。

const fs = require('fs'),
    path = require('path'),
    axios = require("axios")

const createDir = path => !fs.existsSync(path) && fs.mkdirSync(path)
const mirrorDirectoryPaths = async ({ cacheLocation, url }) => {
    createDir(cacheLocation)
    const dirs = [], scriptPath = url.replace(/:\/\/|:/g, "-")

    let currentDir = path.dirname(scriptPath)
    while (currentDir !== '.') {
        dirs.unshift(currentDir)
        currentDir = path.dirname(currentDir)
    }
    dirs.forEach(d => createDir(`${cacheLocation}${d}`))
    return `${cacheLocation}${scriptPath}`
}

const cacheIndex = {}
const writeToDiskCache = async ({ cacheLocation, url }) => {
    //Write a file to the local disk cache for rollup to pick up.
    //If the file is already existing use it instead of writing a new one.
    const cached = cacheIndex[url]
    if (cached) return cached

    const cacheFile = await mirrorDirectoryPaths({ cacheLocation, url }),
        data = (await axiosInstance.get(url).catch((e) => { console.log(url, e) })).data
    fs.writeFileSync(cacheFile, data)
    cacheIndex[url] = cacheFile

    return cacheFile
}

const urlPlugin = (options = { cacheLocation }) => {
    return {
        async resolveId(importee, importer) {
            //We importing from a URL
            if (/^https?:\/\//.test(importee)) {
                return await writeToDiskCache({ cacheLocation: options.cacheLocation, url: importee })
            }
            //We are importing from a file within the cacheLocation (originally from a URL) and need to continue the cache import chain.
            if (importer && importer.startsWith(options.cacheLocation) && /^..?\//.test(importee)) {
                const importerUrl = Object.keys(cacheIndex).find(key => cacheIndex[key] === importer),
                    importerPath = path.dirname(importerUrl),
                    importeeUrl = path.normalize(`${importerPath}/${importee}`).replace(":\\", "://").replace(/\\/g, "/")
                return await writeToDiskCache({ cacheLocation: options.cacheLocation, url: importeeUrl })
            }
        }
    }
}


4
一直在寻找相同的功能。想象一下,如果有绝对 URL 导入功能,Rollup 就可以用作静态网站生成器! - Chuanqi Sun
1
没错。只要没有跨域问题,为浏览器开发提供了非常好的体验。我已经更新了代码片段,解决了一些最初的问题。 - BlueWater86
@BlueWater86,你的代码片段中存在一个隐藏问题:urlPlugin (options = { cacheLocation }) => 会在未定义选项时初始化参数 options 的默认值...使用属性缩写,因此尝试读取未定义的 cacheLocation 变量。也许你的意思是:(options = { cacheLocation: '' }) => 或者 TypeScript 的方式 (options: { cacheLocation }) => - Thomas Di G

0

这个插件和下面的配置对我很有用: https://github.com/mjackson/rollup-plugin-url-resolve

import typescript from "@rollup/plugin-typescript";
import urlResolve from "rollup-plugin-url-resolve";

export default {
  output: {
    format: "esm",
  },
  plugins: [
    typescript({ lib: ["es5", "es6", "dom"], target: "es5" }),
    urlResolve(),
  ],
};

你可以显然地移除 TypeScript 插件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接