最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Trying to prevent Vite HMR from adding the module script to certain files - Stack Overflow

programmeradmin3浏览0评论

Basically, I have partial HTML template files that use the file extension *.tpl.html (thanks, legacy AngularJS). These files are being loaded through a custom plugin to ensure that when they're imported into JS/TS, the default export is a string containing the location of that file. The import works, but Vite HMR server is trying to inject the <script> into the HTML of that file, which causes some issues. I think the weird thing to me is that it tries to treat every *.html file as if it were an index.html entry file?

It doesn't look like there's an out-of-the-box way to prevent certain files from getting the script tag injected, but I was wondering if there's any other way to handle that issue. I've played around a bit with a serve-specific plugin to try and either skip the injection or to maybe remove injection after it's been injected, but I haven't been able to figure that out (see bottom of question for the serve-specific plugin)

Admittedly, this is probably a weird thing to be trying to do in the first place, but I feel like it should be doable in Vite and maybe I'm just missing something.

Background: I have an legacy AngularJS application that we're migrating to React. The core of the application is still AngularJS at the top level. In the AngularJS app, we have components that use partial HTML templates as modules, so you can import those modules and get back their file location (for use in passing the file location into the AngularJS templateUrl).

For example:

import templateLocation from "@/path/to/file.tpl.html"
...
angular.directive({
    ...,
    templateUrl: templateLocation,
});

We created a custom plugin that handles transforming/loading the *.tpl.html files as modules so that we get the proper string templateUrl when imported, but when the browser tries to load that *.tpl.html file from the HMR server, Vite ends up injecting the <script type="module"> code into the template file, and it ends up violating some rules in AngularJS (specifically the fact that directive templates can only have a single HTML tag as the parentNode).

Serve-specific Plugin

export function tplHtmlServePlugin(): Plugin {
    return {
        name: 'tpl-html-plugin:serve',
        enforce: 'pre',
        apply: 'serve',

        /**
         * Add ?tpl-html-plugin to the end of the import path so we can distinguish between these files in the load() hook
         * (this part is working fine)
         */
        async resolveId(id, importer, options) {
            if (htmlFileRegex.test(id) && !options.isEntry) {
                let res = await this.resolve(id, importer, {
                    skipSelf: true,
                    ...options,
                });

                if (!res || res.external) return res;

                return res.id + postfix;
            }
        },

        /**
         * loads *.tpl.html files as a module that exports the relative path to the file as the default export
         * (this part is working fine)
         */
        async load(id: string) {
            if (!id.endsWith(postfix)) return;

            const relativePath = id.replace(/.*\/src/, '/src');
            console_log(`Transforming ${id} to export default "${relativePath}"`);

            return `export default ${JSON.stringify(relativePath)}`;
        },

        /**
         * Try to do something here to prevent/remove the module script from ending up the the *.tpl.html file when it's loaded by the browser?
         * (I'm not sure I'm doing the right thing here, or if it needs to be a separate plugin?)
         */
        async transformIndexHtml(html, { filename, server }) {
            if (!filename || !htmlFileRegex.test(filename)) return html;

            server?.ws.send({ type: 'full-reload' });
            return html
                .replace(/<script type="module".*?<\/script>/g, '')
                .replace(/<script nomodule/g, '<script');
        },
    };
}
发布评论

评论列表(0)

  1. 暂无评论