-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
index.ts
100 lines (96 loc) · 3.07 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import type { Plugin, IndexHtmlTransformResult } from 'vite'
import { parse } from 'node-html-parser'
import type { Options } from '../index'
export function dynamicBase(options?: Options): Plugin {
const defaultOptions:Options ={
publicPath: 'window.__dynamic_base__',
transformIndexHtml: false // maybe dfault true
}
const {
publicPath,
transformIndexHtml
} = {...defaultOptions ,...(options || {})}
const preloadHelperId = 'vite/preload-helper'
let assetsDir = 'assets'
let base = '/'
return {
name: 'vite-plugin-dynamic-base',
enforce: 'post',
apply: 'build',
configResolved(resolvedConfig) {
assetsDir = resolvedConfig.build.assetsDir
base = resolvedConfig.base
},
transform(code, id) {
if (id === preloadHelperId) {
code = code.replace(/(\${base})/g, `\${${publicPath}}$1`)
return {
code
}
}
},
generateBundle({ format }, bundle) {
if (format !== 'es') {
return
}
const assetsMarker = `${base}${assetsDir}/`
const assetsMarkerRE = new RegExp(`("${assetsMarker}*.*.*")`, 'g')
for (const file in bundle) {
const chunk = bundle[file]
if (chunk.type === 'chunk' && chunk.code.indexOf(assetsMarker) > -1) {
chunk.code = chunk.code.replace(assetsMarkerRE, `${publicPath}+$1`)
}
}
},
transformIndexHtml: {
enforce: 'post',
transform(html): IndexHtmlTransformResult {
if(!transformIndexHtml) {
return html
}
const document = parse(html, { comment: true })
const assetsMarker = `${base}${assetsDir}/`
const assetsTags = document.querySelectorAll(`link[href^="${assetsMarker}"],script[src^="${assetsMarker}"]`)
const preloads = assetsTags.map(o => {
const result = {
parentTagName: o.parentNode.rawTagName,
tagName: o.rawTagName,
attrs: Object.assign({}, o.attrs)
}
o.parentNode.removeChild(o)
return result
})
const injectCode = ` <script>
var preloads = ${JSON.stringify(preloads)};
function assign() {
var target = arguments[0];
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
for(var i = 0; i < preloads.length; i++){
var item = preloads[i]
var childNode = document.createElement(item.tagName);
assign(childNode, item.attrs)
if(${publicPath}) {
if(item.tagName == 'link') {
assign(childNode, { href: ${publicPath} + item.attrs.href })
} else if (item.tagName == 'script') {
assign(childNode, { src: ${publicPath} + item.attrs.src })
}
}
document.getElementsByTagName(item.parentTagName)[0].appendChild(childNode);
}
</script>
</head>`
return document.outerHTML.replace('</head>', injectCode)
}
}
}
}