Sets import.meta.env.BASE_URL correctly in dev (#3955)
This commit is contained in:
parent
963100fb27
commit
92b48b1525
7 changed files with 115 additions and 66 deletions
5
.changeset/strong-squids-hide.md
Normal file
5
.changeset/strong-squids-hide.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Set import.meta.env.BASE_URL in dev mode
|
|
@ -79,6 +79,7 @@ export default function envVitePlugin({
|
|||
if (privateEnv) {
|
||||
privateEnv.SITE = astroConfig.site ? `'${astroConfig.site}'` : 'undefined';
|
||||
privateEnv.SSR = JSON.stringify(true);
|
||||
privateEnv.BASE_URL = astroConfig.base ? `'${astroConfig.base}'` : undefined;
|
||||
const entries = Object.entries(privateEnv).map(([key, value]) => [
|
||||
`import.meta.env.${key}`,
|
||||
value,
|
||||
|
@ -88,6 +89,7 @@ export default function envVitePlugin({
|
|||
replacements = Object.assign(replacements, {
|
||||
'import.meta.env.SITE': astroConfig.site ? `'${astroConfig.site}'` : 'undefined',
|
||||
'import.meta.env.SSR': JSON.stringify(true),
|
||||
'import.meta.env.BASE_URL': astroConfig.base ? `'${astroConfig.base}'` : undefined,
|
||||
// This catches destructed `import.meta.env` calls,
|
||||
// BUT we only want to inject private keys referenced in the file.
|
||||
// We overwrite this value on a per-file basis.
|
||||
|
|
|
@ -1,85 +1,123 @@
|
|||
import { expect } from 'chai';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
import * as cheerio from 'cheerio';
|
||||
|
||||
describe('Environment Variables', () => {
|
||||
/** @type {import('./test-utils').Fixture} */
|
||||
let fixture;
|
||||
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/astro-envs/',
|
||||
});
|
||||
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('builds without throwing', async () => {
|
||||
expect(true).to.equal(true);
|
||||
});
|
||||
|
||||
it('does render public env and private env', async () => {
|
||||
let indexHtml = await fixture.readFile('/index.html');
|
||||
|
||||
expect(indexHtml).to.include('CLUB_33');
|
||||
expect(indexHtml).to.include('BLUE_BAYOU');
|
||||
});
|
||||
|
||||
it('does render destructured public env and private env', async () => {
|
||||
let indexHtml = await fixture.readFile('/destructured/index.html');
|
||||
|
||||
expect(indexHtml).to.include('CLUB_33');
|
||||
expect(indexHtml).to.include('BLUE_BAYOU');
|
||||
});
|
||||
|
||||
it('does render builtin SITE env', async () => {
|
||||
let indexHtml = await fixture.readFile('/index.html');
|
||||
expect(indexHtml).to.include('http://example.com');
|
||||
});
|
||||
|
||||
it('does render destructured builtin SITE env', async () => {
|
||||
let indexHtml = await fixture.readFile('/destructured/index.html');
|
||||
|
||||
expect(indexHtml).to.include('http://example.com');
|
||||
});
|
||||
|
||||
it('includes public env in client-side JS', async () => {
|
||||
let dirs = await fixture.readdir('/');
|
||||
let found = false;
|
||||
|
||||
// Look in all of the .js files to see if the public env is inlined.
|
||||
// Testing this way prevents hardcoding expected js files.
|
||||
// If we find it in any of them that's good enough to know its working.
|
||||
await Promise.all(
|
||||
dirs.map(async (path) => {
|
||||
if (path.endsWith('.js')) {
|
||||
let js = await fixture.readFile(`/${path}`);
|
||||
if (js.includes('BLUE_BAYOU')) {
|
||||
found = true;
|
||||
describe('Build', () => {
|
||||
before(async () => {
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('builds without throwing', async () => {
|
||||
expect(true).to.equal(true);
|
||||
});
|
||||
|
||||
it('does render public env and private env', async () => {
|
||||
let indexHtml = await fixture.readFile('/index.html');
|
||||
|
||||
expect(indexHtml).to.include('CLUB_33');
|
||||
expect(indexHtml).to.include('BLUE_BAYOU');
|
||||
});
|
||||
|
||||
it('does render destructured public env and private env', async () => {
|
||||
let indexHtml = await fixture.readFile('/destructured/index.html');
|
||||
|
||||
expect(indexHtml).to.include('CLUB_33');
|
||||
expect(indexHtml).to.include('BLUE_BAYOU');
|
||||
});
|
||||
|
||||
it('does render builtin SITE env', async () => {
|
||||
let indexHtml = await fixture.readFile('/index.html');
|
||||
expect(indexHtml).to.include('http://example.com');
|
||||
});
|
||||
|
||||
it('does render destructured builtin SITE env', async () => {
|
||||
let indexHtml = await fixture.readFile('/destructured/index.html');
|
||||
|
||||
expect(indexHtml).to.include('http://example.com');
|
||||
});
|
||||
|
||||
it('does render builtin BASE_URL env', async () => {
|
||||
let indexHtml = await fixture.readFile('/index.html');
|
||||
expect(indexHtml).to.include('/blog');
|
||||
});
|
||||
|
||||
it('includes public env in client-side JS', async () => {
|
||||
let dirs = await fixture.readdir('/');
|
||||
let found = false;
|
||||
|
||||
// Look in all of the .js files to see if the public env is inlined.
|
||||
// Testing this way prevents hardcoding expected js files.
|
||||
// If we find it in any of them that's good enough to know its working.
|
||||
await Promise.all(
|
||||
dirs.map(async (path) => {
|
||||
if (path.endsWith('.js')) {
|
||||
let js = await fixture.readFile(`/${path}`);
|
||||
if (js.includes('BLUE_BAYOU')) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
expect(found).to.equal(true, 'found the public env variable in the JS build');
|
||||
})
|
||||
);
|
||||
|
||||
expect(found).to.equal(true, 'found the public env variable in the JS build');
|
||||
});
|
||||
|
||||
it('does not include private env in client-side JS', async () => {
|
||||
let dirs = await fixture.readdir('/');
|
||||
let found = false;
|
||||
|
||||
// Look in all of the .js files to see if the public env is inlined.
|
||||
// Testing this way prevents hardcoding expected js files.
|
||||
// If we find it in any of them that's good enough to know its NOT working.
|
||||
await Promise.all(
|
||||
dirs.map(async (path) => {
|
||||
if (path.endsWith('.js')) {
|
||||
let js = await fixture.readFile(`/${path}`);
|
||||
if (js.includes('CLUB_33')) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
expect(found).to.equal(false, 'found the private env variable in the JS build');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not include private env in client-side JS', async () => {
|
||||
let dirs = await fixture.readdir('/');
|
||||
let found = false;
|
||||
describe('Development', () => {
|
||||
/** @type {import('./test-utils').DevServer} */
|
||||
let devServer;
|
||||
before(async () => {
|
||||
devServer = await fixture.startDevServer();
|
||||
});
|
||||
after(async () => {
|
||||
await devServer.stop();
|
||||
});
|
||||
|
||||
// Look in all of the .js files to see if the public env is inlined.
|
||||
// Testing this way prevents hardcoding expected js files.
|
||||
// If we find it in any of them that's good enough to know its NOT working.
|
||||
await Promise.all(
|
||||
dirs.map(async (path) => {
|
||||
if (path.endsWith('.js')) {
|
||||
let js = await fixture.readFile(`/${path}`);
|
||||
if (js.includes('CLUB_33')) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
it('does render builtin BASE_URL env', async () => {
|
||||
let res = await fixture.fetch('/blog/');
|
||||
expect(res.status).to.equal(200);
|
||||
let indexHtml = await res.text();
|
||||
let $ = cheerio.load(indexHtml);
|
||||
expect($('#base-url').text()).to.equal('/blog/');
|
||||
});
|
||||
|
||||
expect(found).to.equal(false, 'found the private env variable in the JS build');
|
||||
it('does render destructured builtin SITE env', async () => {
|
||||
let res = await fixture.fetch('/blog/destructured/');
|
||||
expect(res.status).to.equal(200);
|
||||
let indexHtml = await res.text();
|
||||
let $ = cheerio.load(indexHtml);
|
||||
expect($('#base-url').text()).to.equal('/blog/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,5 +4,6 @@ import vue from '@astrojs/vue';
|
|||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: 'http://example.com',
|
||||
base: '/blog',
|
||||
integrations: [vue()],
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@ export default {
|
|||
return {
|
||||
PUBLIC_PLACE: import.meta.env.PUBLIC_PLACE,
|
||||
SECRET_PLACE: import.meta.env.SECRET_PLACE,
|
||||
BASE_URL: import.meta.env.BASE_URL,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,3 +4,4 @@ const { PUBLIC_PLACE, SECRET_PLACE, SITE } = import.meta.env;
|
|||
<environment-variable>{PUBLIC_PLACE}</environment-variable>
|
||||
<environment-variable>{SECRET_PLACE}</environment-variable>
|
||||
<environment-variable>{SITE}</environment-variable>
|
||||
<environment-variable id="base-url">{import.meta.env.BASE_URL}</environment-variable>
|
||||
|
|
|
@ -4,4 +4,5 @@ import Client from '../components/Client.vue';
|
|||
<environment-variable>{import.meta.env.PUBLIC_PLACE}</environment-variable>
|
||||
<environment-variable>{import.meta.env.SECRET_PLACE}</environment-variable>
|
||||
<environment-variable>{import.meta.env.SITE}</environment-variable>
|
||||
<environment-variable id="base-url">{import.meta.env.BASE_URL}</environment-variable>
|
||||
<Client client:load />
|
||||
|
|
Loading…
Reference in a new issue