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');
},
};
}
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744539579a4579642.html
评论列表(0条)