Skip to content

Commit

Permalink
feat: dedupe option
Browse files Browse the repository at this point in the history
close #1302
  • Loading branch information
yyx990803 committed Jan 3, 2021
1 parent b665b92 commit 7858e62
Show file tree
Hide file tree
Showing 16 changed files with 110 additions and 24 deletions.
7 changes: 7 additions & 0 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ export default ({ command, mode }) => {

Vite will not be able to know that the file needs to be transformed to JavaScript (instead of being served directly as a static file). `transformInclude` allows you to explicitly declare the file type to always be transformed and served as JavaScript.

### dedupe

- **Type:** `string[]`

If you have duplicated copies of the same depdendency in your app (likely due to hoisting or linked packages in monorepos), use this option to force Vite to always resolve listed dependencies to the same copy (from
project root).

### logLevel

- **Type:** `'info' | 'warn' | 'error' | 'silent'`
Expand Down
7 changes: 7 additions & 0 deletions packages/playground/optimize-deps-linked-include/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { msg } from './foo.js'

import { useState } from 'react'

export function useCount() {
return useState(0)
}
8 changes: 8 additions & 0 deletions packages/playground/optimize-deps-linked-include/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "optimize-deps-linked-include",
"version": "0.0.0",
"main": "index.js",
"dependencies": {
"react": "17.0.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ test('dynamic imports from cjs dep (react)', async () => {
expect(await page.textContent('.cjs-dynamic button')).toBe('count is 1')
})

test('dedupe', async () => {
expect(await page.textContent('.dedupe button')).toBe('count is 0')
await page.click('.dedupe button')
expect(await page.textContent('.dedupe button')).toBe('count is 1')
})

test('cjs borwser field (axios)', async () => {
expect(await page.textContent('.cjs-browser-field')).toBe('pong')
})
Expand Down
22 changes: 22 additions & 0 deletions packages/playground/optimize-deps/dedupe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// test importing both default and named exports from a CommonJS module
// React is the ultimate test of this because its dynamic exports assignments
// are not statically detectable by @rollup/plugin-commonjs.
import React, { useState } from 'react'
import ReactDOM from 'react-dom'
import { useCount } from 'optimize-deps-linked-include'

function App() {
const [count, setCount] = useCount()

return React.createElement(
'button',
{
onClick() {
setCount(count + 1)
}
},
`count is ${count}`
)
}

ReactDOM.render(React.createElement(App), document.querySelector('.dedupe'))
6 changes: 5 additions & 1 deletion packages/playground/optimize-deps/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ <h2>CommonJS dynamic import (react)</h2>
<div class="cjs-dynamic"></div>
<script type="module" src="./cjs-dynamic.js"></script>

<h2>Dedupe (dep in linked & optimized package)</h2>
<div class="dedupe"></div>
<script type="module" src="./dedupe.js"></script>

<h2>CommonJS w/ browser field mapping (axios)</h2>
<div>This should show ping: <span class="cjs-browser-field"></span></div>

Expand All @@ -27,6 +31,6 @@ <h2>Optimizing force included dep even when it's linked</h2>
import { camelCase } from 'optimize-deps-linked'
document.querySelector('.deps-linked').textContent = camelCase('foo-bar-baz')

import { msg } from 'linked-force-include'
import { msg } from 'optimize-deps-linked-include'
document.querySelector('.force-include').textContent = msg
</script>

This file was deleted.

This file was deleted.

2 changes: 1 addition & 1 deletion packages/playground/optimize-deps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
"react-dom": "^17.0.1",
"resolve-linked": "0.0.0",
"optimize-deps-linked": "0.0.0",
"linked-force-include": "link:./linked-force-include"
"optimize-deps-linked-include": "0.0.0"
}
}
4 changes: 3 additions & 1 deletion packages/playground/optimize-deps/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
* @type {import('vite').UserConfig}
*/
module.exports = {
dedupe: ['react'],

optimizeDeps: {
include: ['linked-force-include']
include: ['optimize-deps-linked-include']
},

build: {
Expand Down
15 changes: 10 additions & 5 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ export interface UserConfig {
* Dep optimization options
*/
optimizeDeps?: DepOptimizationOptions
/**
* Force Vite to always resolve listed dependencies to the same copy (from
* project root).
*/
dedupe?: string[]
/**
* Log level.
* Default: 'info'
Expand Down Expand Up @@ -416,11 +421,11 @@ async function loadConfigFromFile(
plugins: [
// use esbuild + node-resolve to support .ts files
esbuildPlugin({ target: 'es2019' }),
resolvePlugin(
path.dirname(resolvedPath),
true /* isBuild */,
false /* disallow src code only resolves */
)
resolvePlugin({
root: path.dirname(resolvedPath),
isBuild: true,
asSrc: false
})
]
})

Expand Down
7 changes: 6 additions & 1 deletion packages/vite/src/node/optimizer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,12 @@ export async function optimizeDeps(
aliasPlugin({ entries: config.alias }),
depAssetExternalPlugin(config),
// TODO user pre plugins?
resolvePlugin(config.root, true /* isBuild */, false /* asSrc */),
resolvePlugin({
root: config.root,
dedupe: config.dedupe,
isBuild: true,
asSrc: false
}),
jsonPlugin({
preferConst: true,
namedExports: true
Expand Down
7 changes: 6 additions & 1 deletion packages/vite/src/node/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ export async function resolvePlugins(
return [
aliasPlugin({ entries: config.alias }),
...prePlugins,
resolvePlugin(config.root, isBuild, true),
resolvePlugin({
root: config.root,
dedupe: config.dedupe,
isBuild,
asSrc: true
}),
htmlPlugin(),
cssPlugin(config),
config.esbuild !== false ? esbuildPlugin(config.esbuild) : null,
Expand Down
25 changes: 21 additions & 4 deletions packages/vite/src/node/plugins/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,24 @@ const debug = createDebugger('vite:resolve-details', {
onlyWhenFocused: true
})

export function resolvePlugin(
root: string,
isBuild: boolean,
interface ResolveOptions {
root: string
isBuild: boolean
/**
* src code mode also attempts the following:
* - resolving /xxx as URLs
* - resolving bare imports from optimized deps
*/
asSrc: boolean
): Plugin {
dedupe?: string[]
}

export function resolvePlugin({
root,
isBuild,
asSrc,
dedupe
}: ResolveOptions): Plugin {
let server: ViteDevServer

return {
Expand Down Expand Up @@ -124,6 +132,8 @@ export function resolvePlugin(
id,
importer ? path.dirname(importer) : root,
isBuild,
dedupe,
root,
server
))
) {
Expand Down Expand Up @@ -180,10 +190,17 @@ export function tryNodeResolve(
id: string,
basedir: string,
isBuild = true,
dedupe?: string[],
dedupeRoot?: string,
server?: ViteDevServer
): PartialResolvedId | undefined {
const deepMatch = id.match(deepImportRE)
const pkgId = deepMatch ? deepMatch[1] || deepMatch[2] : id

if (dedupe && dedupeRoot && dedupe.includes(pkgId)) {
basedir = dedupeRoot
}

const pkg = resolvePackageData(pkgId, basedir)

if (!pkg) {
Expand Down
12 changes: 8 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4628,10 +4628,6 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=

"linked-force-include@link:./packages/playground/optimize-deps/linked-force-include":
version "0.0.0"
uid ""

linkify-it@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf"
Expand Down Expand Up @@ -6102,6 +6098,14 @@ react-refresh@^0.9.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf"
integrity sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==

react@17.0.0:
version "17.0.0"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.0.tgz#ad96d5fa1a33bb9b06d0cc52672f7992d84aa662"
integrity sha512-rG9bqS3LMuetoSUKHN8G3fMNuQOePKDThK6+2yXFWtoeTDLVNh/QCaxT+Jr+rNf4lwNXpx+atdn3Aa0oi8/6eQ==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"

react@^17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
Expand Down

0 comments on commit 7858e62

Please sign in to comment.