Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: preserve process env vars in lib build #8090

Merged
merged 12 commits into from Jun 5, 2022
44 changes: 22 additions & 22 deletions packages/vite/src/node/plugins/define.ts
Expand Up @@ -10,15 +10,23 @@ const isNonJsRequest = (request: string): boolean => nonJsRe.test(request)

export function definePlugin(config: ResolvedConfig): Plugin {
const isBuild = config.command === 'build'

const processNodeEnv: Record<string, string> = {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || config.mode),
'global.process.env.NODE_ENV': JSON.stringify(
process.env.NODE_ENV || config.mode
),
'globalThis.process.env.NODE_ENV': JSON.stringify(
process.env.NODE_ENV || config.mode
)
const isBuildLib = isBuild && config.build.lib

// ignore replace process.env in lib build
const processEnv: Record<string, string> = {}
const processNodeEnv: Record<string, string> = {}
if (!isBuildLib) {
const nodeEnv = process.env.NODE_ENV || config.mode
Object.assign(processEnv, {
'process.env.': `({}).`,
'global.process.env.': `({}).`,
'globalThis.process.env.': `({}).`
})
Object.assign(processNodeEnv, {
'process.env.NODE_ENV': JSON.stringify(nodeEnv),
'global.process.env.NODE_ENV': JSON.stringify(nodeEnv),
'globalThis.process.env.NODE_ENV': JSON.stringify(nodeEnv)
})
}

const userDefine: Record<string, string> = {}
Expand All @@ -27,7 +35,8 @@ export function definePlugin(config: ResolvedConfig): Plugin {
userDefine[key] = typeof val === 'string' ? val : JSON.stringify(val)
}

// during dev, import.meta properties are handled by importAnalysis plugin
// during dev, import.meta properties are handled by importAnalysis plugin.
// ignore replace import.meta.env in lib build
const importMetaKeys: Record<string, string> = {}
if (isBuild) {
const env: Record<string, any> = {
Expand All @@ -47,22 +56,13 @@ export function definePlugin(config: ResolvedConfig): Plugin {
function generatePattern(
ssr: boolean
): [Record<string, string | undefined>, RegExp | null] {
const processEnv: Record<string, string> = {}
const isNeedProcessEnv = !ssr || config.ssr?.target === 'webworker'

if (isNeedProcessEnv) {
Object.assign(processEnv, {
'process.env.': `({}).`,
'global.process.env.': `({}).`,
'globalThis.process.env.': `({}).`
})
}
const replaceProcessEnv = !ssr || config.ssr?.target === 'webworker'

const replacements: Record<string, string> = {
...(isNeedProcessEnv ? processNodeEnv : {}),
...(replaceProcessEnv ? processNodeEnv : {}),
...userDefine,
...importMetaKeys,
...processEnv
...(replaceProcessEnv ? processEnv : {})
}

const replacementsKeys = Object.keys(replacements)
Expand Down
28 changes: 13 additions & 15 deletions playground/lib/__tests__/lib.spec.ts
@@ -1,11 +1,9 @@
import path from 'path'
import fs from 'fs'
import {
isBuild,
isServe,
page,
readFile,
serverLogs,
testDir,
untilUpdated
} from '~utils'

Expand All @@ -16,20 +14,14 @@ describe.runIf(isBuild)('build', () => {

test('umd', async () => {
expect(await page.textContent('.umd')).toBe('It works')
const code = fs.readFileSync(
path.join(testDir, 'dist/my-lib-custom-filename.umd.js'),
'utf-8'
)
const code = readFile('dist/my-lib-custom-filename.umd.js')
// esbuild helpers are injected inside of the UMD wrapper
expect(code).toMatch(/^\(function\(/)
})

test('iife', async () => {
expect(await page.textContent('.iife')).toBe('It works')
const code = fs.readFileSync(
path.join(testDir, 'dist/my-lib-custom-filename.iife.js'),
'utf-8'
)
const code = readFile('dist/my-lib-custom-filename.iife.js')
// esbuild helpers are injected inside of the IIFE wrapper
expect(code).toMatch(/^const MyLib=function\(\){"use strict";/)
})
Expand All @@ -39,10 +31,7 @@ describe.runIf(isBuild)('build', () => {
() => page.textContent('.dynamic-import-message'),
'hello vite'
)
const code = fs.readFileSync(
path.join(testDir, 'dist/lib/dynamic-import-message.es.mjs'),
'utf-8'
)
const code = readFile('dist/lib/dynamic-import-message.es.js')
expect(code).not.toMatch('__vitePreload')

// Test that library chunks are hashed
Expand All @@ -55,6 +44,15 @@ describe.runIf(isBuild)('build', () => {
expect(log).not.toMatch('All "@import" rules must come first')
})
})

test('preserve process.env', () => {
const es = readFile('dist/my-lib-custom-filename.mjs')
const iife = readFile('dist/my-lib-custom-filename.iife.js')
const umd = readFile('dist/my-lib-custom-filename.umd.js')
expect(es).toMatch('process.env.NODE_ENV')
expect(iife).toMatch('process.env.NODE_ENV')
expect(umd).toMatch('process.env.NODE_ENV')
})
})

test.runIf(isServe)('dev', async () => {
Expand Down
9 changes: 9 additions & 0 deletions playground/lib/index.dist.html
Expand Up @@ -4,6 +4,15 @@
<div class="iife"></div>
<div class="dynamic-import-message"></div>

<script>
// shim test preserve process.env.NODE_ENV
globalThis.process = {
env: {
NODE_ENV: 'production'
}
}
</script>

<script type="module">
import myLib from './my-lib-custom-filename.mjs'

Expand Down
3 changes: 3 additions & 0 deletions playground/lib/src/main.js
Expand Up @@ -3,4 +3,7 @@ export default function myLib(sel) {
console.log({ ...'foo' })

document.querySelector(sel).textContent = 'It works'

// Env vars should not be replaced
console.log(process.env.NODE_ENV)
}