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: add resolve.preserveSymlinks option #4708

Merged
merged 6 commits into from Sep 13, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/config/index.md
Expand Up @@ -206,6 +206,16 @@ export default defineConfig(async ({ command, mode }) => {

List of file extensions to try for imports that omit extensions. Note it is **NOT** recommended to omit extensions for custom import types (e.g. `.vue`) since it can interfere with IDE and type support.

### resolve.preserveSymlinks

- **Type:** `boolean`
- **Default:** `false`

Enabling this setting causes vite to determine file identity by the original file path (i.e. the path without following symlinks) instead of the real file path (i.e. the path after following symlinks).

- **Related:** [esbuild#preserve-symlinks](https://esbuild.github.io/api/#preserve-symlinks), [webpack#resolve.symlinks
](https://webpack.js.org/configuration/resolve/#resolvesymlinks)

### css.modules

- **Type:**
Expand Down
@@ -0,0 +1,9 @@
test('should have no 404s', () => {
browserLogs.forEach((msg) => {
expect(msg).not.toMatch('404')
})
})

test('not-preserve-symlinks', async () => {
expect(await page.textContent('#root')).toBe('hello vite')
})
108 changes: 108 additions & 0 deletions packages/playground/preserve-symlinks/__tests__/serve.js
@@ -0,0 +1,108 @@
// @ts-check
// this is automtically detected by scripts/jestPerTestSetup.ts and will replace
// the default e2e test serve behavior

const path = require('path')
const http = require('http')
const sirv = require('sirv')
const fs = require('fs')

const port = (exports.port = 9527)

/**
* @param {string} root
* @param {boolean} isBuildTest
*/
exports.serve = async function serve(root, isBuildTest) {
const testDist = path.resolve(__dirname, '../moduleA/dist')

if (fs.existsSync(testDist)) {
emptyDir(testDist)
} else {
fs.mkdirSync(testDist, { recursive: true })
}

fs.symlinkSync(
path.resolve(testDist, '../src/index.js'),
path.resolve(testDist, 'symlinks-moduleA.esm.js')
)

if (!isBuildTest) {
const { createServer } = require('vite')
process.env.VITE_INLINE = 'inline-serve'
let viteServer = await (
await createServer({
root: root,
logLevel: 'silent',
server: {
watch: {
usePolling: true,
interval: 100
},
host: true,
fs: {
strict: !isBuildTest
}
},
build: {
target: 'esnext'
}
})
).listen()
// use resolved port/base from server
const base = viteServer.config.base === '/' ? '' : viteServer.config.base
const url =
(global.viteTestUrl = `http://localhost:${viteServer.config.server.port}${base}`)
await page.goto(url)

return viteServer
} else {
const { build } = require('vite')
await build({
root,
logLevel: 'silent',
configFile: path.resolve(__dirname, '../vite.config.js')
})

// start static file server
const serve = sirv(path.resolve(root, 'dist'))
const httpServer = http.createServer((req, res) => {
if (req.url === '/ping') {
res.statusCode = 200
res.end('pong')
} else {
serve(req, res)
}
})

return new Promise((resolve, reject) => {
try {
const server = httpServer.listen(port, async () => {
await page.goto(`http://localhost:${port}`)
resolve({
// for test teardown
async close() {
await new Promise((resolve) => {
server.close(resolve)
})
}
})
})
} catch (e) {
reject(e)
}
})
}
}

function emptyDir(dir) {
for (const file of fs.readdirSync(dir)) {
const abs = path.resolve(dir, file)
if (fs.lstatSync(abs).isDirectory()) {
emptyDir(abs)
fs.rmdirSync(abs)
} else {
fs.unlinkSync(abs)
}
}
}
13 changes: 13 additions & 0 deletions packages/playground/preserve-symlinks/index.html
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
17 changes: 17 additions & 0 deletions packages/playground/preserve-symlinks/moduleA/package.json
@@ -0,0 +1,17 @@
{
"name": "@symlinks/moduleA",
"version": "0.0.0",
"module": "dist/symlinks-moduleA.esm.js",
"main": "dist/symlinks-moduleA.cjs.js",
"preconstruct": {
"entrypoints": [
"index.js"
]
},
"scripts": {
"dev": "preconstruct dev"
},
"devDependencies": {
"@preconstruct/cli": "^2.0.6"
}
}
3 changes: 3 additions & 0 deletions packages/playground/preserve-symlinks/moduleA/src/data.js
@@ -0,0 +1,3 @@
export const data = {
msg: 'hello vite'
}
5 changes: 5 additions & 0 deletions packages/playground/preserve-symlinks/moduleA/src/index.js
@@ -0,0 +1,5 @@
import { data } from './data'

export function sayHi() {
return data
}
13 changes: 13 additions & 0 deletions packages/playground/preserve-symlinks/package.json
@@ -0,0 +1,13 @@
{
"name": "preserveSymlinks",
"version": "0.0.0",
"scripts": {
"dev": "vite --force",
"build": "vite build",
"serve": "vite preview"
},
"workspaces": {},
"dependencies": {
"@symlinks/moduleA": "link:./moduleA"
}
}
3 changes: 3 additions & 0 deletions packages/playground/preserve-symlinks/src/main.js
@@ -0,0 +1,3 @@
import { sayHi } from '@symlinks/moduleA'

document.getElementById('root').innerText = sayHi().msg
6 changes: 6 additions & 0 deletions packages/playground/preserve-symlinks/vite.config.js
@@ -0,0 +1,6 @@
// https://vitejs.dev/config/
module.exports = {
resolve: {
preserveSymlinks: false
}
}
1 change: 1 addition & 0 deletions packages/vite/src/node/config.ts
Expand Up @@ -432,6 +432,7 @@ export async function resolveConfig(
...config.optimizeDeps,
esbuildOptions: {
keepNames: config.optimizeDeps?.keepNames,
preserveSymlinks: config.resolve?.preserveSymlinks,
...config.optimizeDeps?.esbuildOptions
}
}
Expand Down