UNPKG

8.34 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.generateEnvModule = exports.wrapImportProxy = exports.wrapHtmlResponse = exports.wrapImportMeta = exports.getMetaUrlPath = void 0;
7const path_1 = __importDefault(require("path"));
8const postcss_1 = __importDefault(require("postcss"));
9const postcss_modules_1 = __importDefault(require("postcss-modules"));
10const logger_1 = require("../logger");
11const util_1 = require("../util");
12const import_sri_1 = require("./import-sri");
13const SRI_CLIENT_HMR_SNOWPACK = import_sri_1.generateSRI(Buffer.from(util_1.HMR_CLIENT_CODE));
14const SRI_ERROR_HMR_SNOWPACK = import_sri_1.generateSRI(Buffer.from(util_1.HMR_OVERLAY_CODE));
15const importMetaRegex = /import\s*\.\s*meta/;
16function getMetaUrlPath(urlPath, config) {
17 return path_1.default.posix.normalize(path_1.default.posix.join('/', config.buildOptions.metaUrlPath, urlPath));
18}
19exports.getMetaUrlPath = getMetaUrlPath;
20function wrapImportMeta({ code, hmr, env, config, }) {
21 // Create Regex expressions here, since global regex has per-string state
22 const importMetaHotRegex = /import\s*\.\s*meta\s*\.\s*hot/g;
23 const importMetaEnvRegex = /import\s*\.\s*meta\s*\.\s*env/g;
24 // Optimize: replace direct references to `import.meta.hot` by inlining undefined.
25 // Do this first so that we can bail out in the next `import.meta` test.
26 if (!hmr) {
27 code = code.replace(importMetaHotRegex, 'undefined /* [snowpack] import.meta.hot */ ');
28 }
29 if (!importMetaRegex.test(code)) {
30 return code;
31 }
32 let hmrSnippet = ``;
33 if (hmr) {
34 hmrSnippet = `import * as __SNOWPACK_HMR__ from '${getMetaUrlPath('hmr-client.js', config)}';\nimport.meta.hot = __SNOWPACK_HMR__.createHotContext(import.meta.url);\n`;
35 }
36 let envSnippet = ``;
37 if (env) {
38 envSnippet = `import * as __SNOWPACK_ENV__ from '${getMetaUrlPath('env.js', config)}';\n`;
39 // Optimize any direct references `import.meta.env` by inlining the ref
40 code = code.replace(importMetaEnvRegex, '__SNOWPACK_ENV__');
41 // If we still detect references to `import.meta`, assign `import.meta.env` to be safe
42 if (importMetaRegex.test(code)) {
43 envSnippet += `import.meta.env = __SNOWPACK_ENV__;\n`;
44 }
45 }
46 return hmrSnippet + envSnippet + '\n' + code;
47}
48exports.wrapImportMeta = wrapImportMeta;
49function wrapHtmlResponse({ code, hmr, hmrPort, isDev, config, mode, }) {
50 // replace %PUBLIC_URL% (along with surrounding slashes, if any)
51 code = code.replace(/\/?%PUBLIC_URL%\/?/g, isDev ? '/' : config.buildOptions.baseUrl);
52 // replace %MODE%
53 code = code.replace(/%MODE%/g, mode);
54 const snowpackPublicEnv = getSnowpackPublicEnvVariables();
55 code = code.replace(/%SNOWPACK_PUBLIC_.+?%/gi, (match) => {
56 const envVariableName = match.slice(1, -1);
57 if (envVariableName in snowpackPublicEnv) {
58 return snowpackPublicEnv[envVariableName] || '';
59 }
60 logger_1.logger.warn(`Environment variable "${envVariableName}" is not set`);
61 return match;
62 });
63 // Full Page Transformations: Only full page responses should get these transformations.
64 // Any code not containing `<!DOCTYPE html>` is assumed to be an HTML fragment.
65 const isFullPage = code.trim().toLowerCase().startsWith('<!doctype html>');
66 if (hmr && !isFullPage && !config.buildOptions.htmlFragments) {
67 throw new Error(`HTML fragment found!
68HTML fragments (files not starting with "<!doctype html>") are not transformed like full HTML pages.
69Add the missing doctype, or set buildOptions.htmlFragments=true if HTML fragments are expected.`);
70 }
71 if (hmr && isFullPage) {
72 let hmrScript = ``;
73 if (hmrPort) {
74 hmrScript += `<script type="text/javascript">window.HMR_WEBSOCKET_PORT=${hmrPort}</script>\n`;
75 }
76 hmrScript += `<script type="module" integrity="${SRI_CLIENT_HMR_SNOWPACK}" src="${getMetaUrlPath('hmr-client.js', config)}"></script>`;
77 if (config.devOptions.hmrErrorOverlay) {
78 hmrScript += `<script type="module" integrity="${SRI_ERROR_HMR_SNOWPACK}" src="${getMetaUrlPath('hmr-error-overlay.js', config)}"></script>`;
79 }
80 code = util_1.appendHtmlToHead(code, hmrScript);
81 }
82 return code;
83}
84exports.wrapHtmlResponse = wrapHtmlResponse;
85function generateJsonImportProxy({ code, hmr, config, }) {
86 const jsonImportProxyCode = `let json = ${JSON.stringify(JSON.parse(code))};
87export default json;`;
88 return wrapImportMeta({ code: jsonImportProxyCode, hmr, env: false, config });
89}
90function generateCssImportProxy({ code, hmr, config, }) {
91 const cssImportProxyCode = `// [snowpack] add styles to the page (skip if no document exists)
92if (typeof document !== 'undefined') {${hmr
93 ? `
94 import.meta.hot.accept();
95 import.meta.hot.dispose(() => {
96 document.head.removeChild(styleEl);
97 });\n`
98 : ''}
99 const code = ${JSON.stringify(code)};
100
101 const styleEl = document.createElement("style");
102 const codeEl = document.createTextNode(code);
103 styleEl.type = 'text/css';
104 styleEl.appendChild(codeEl);
105 document.head.appendChild(styleEl);
106}`;
107 return wrapImportMeta({ code: cssImportProxyCode, hmr, env: false, config });
108}
109async function generateCssModuleImportProxy({ url, code, hmr, config, }) {
110 let moduleJson;
111 const processor = postcss_1.default([
112 postcss_modules_1.default({
113 getJSON: (_, json) => {
114 moduleJson = json;
115 },
116 }),
117 ]);
118 const result = await processor.process(code, {
119 from: url,
120 to: url + '.proxy.js',
121 });
122 // log any warnings that happened.
123 result
124 .warnings()
125 .forEach((element) => logger_1.logger.warn(`${url} - ${element.text}`, { name: 'snowpack:cssmodules' }));
126 // return the JS+CSS proxy file.
127 return `
128export let code = ${JSON.stringify(result.css)};
129let json = ${JSON.stringify(moduleJson)};
130export default json;
131${hmr
132 ? `
133import * as __SNOWPACK_HMR_API__ from '${getMetaUrlPath('hmr-client.js', config)}';
134import.meta.hot = __SNOWPACK_HMR_API__.createHotContext(import.meta.url);\n`
135 : ``}
136// [snowpack] add styles to the page (skip if no document exists)
137if (typeof document !== 'undefined') {${hmr
138 ? `
139 import.meta.hot.dispose(() => {
140 document && document.head.removeChild(styleEl);
141 });\n`
142 : ``}
143 const styleEl = document.createElement("style");
144 const codeEl = document.createTextNode(code);
145 styleEl.type = 'text/css';
146
147 styleEl.appendChild(codeEl);
148 document.head.appendChild(styleEl);
149}`;
150}
151function generateDefaultImportProxy(url) {
152 return `export default ${JSON.stringify(url)};`;
153}
154async function wrapImportProxy({ url, code, hmr, config, }) {
155 if (typeof code === 'string') {
156 if (util_1.hasExtension(url, '.json')) {
157 return generateJsonImportProxy({ code, hmr, config });
158 }
159 if (util_1.hasExtension(url, '.css')) {
160 // if proxying a CSS file, remove its source map (the path no longer applies)
161 const sanitized = code.replace(/\/\*#\s*sourceMappingURL=[^/]+\//gm, '');
162 return util_1.hasExtension(url, '.module.css')
163 ? generateCssModuleImportProxy({ url, code: sanitized, hmr, config })
164 : generateCssImportProxy({ code: sanitized, hmr, config });
165 }
166 }
167 return generateDefaultImportProxy(url);
168}
169exports.wrapImportProxy = wrapImportProxy;
170function generateEnvModule({ mode, isSSR, }) {
171 const envObject = getSnowpackPublicEnvVariables();
172 envObject.MODE = mode;
173 envObject.NODE_ENV = mode;
174 envObject.SSR = isSSR;
175 return Object.entries(envObject)
176 .map(([key, val]) => {
177 return `export const ${key} = ${JSON.stringify(val)};`;
178 })
179 .join('\n');
180}
181exports.generateEnvModule = generateEnvModule;
182const PUBLIC_ENV_REGEX = /^SNOWPACK_PUBLIC_.+/;
183function getSnowpackPublicEnvVariables() {
184 const envObject = { ...process.env };
185 for (const env of Object.keys(envObject)) {
186 if (!PUBLIC_ENV_REGEX.test(env)) {
187 delete envObject[env];
188 }
189 }
190 return envObject;
191}