Construindo para Produção
Quando for o momento de implementar a nossa aplicação em produção, simplesmente executamos o comando vite build
. Por padrão, este usa <root>/index.html
como o ponto de entrada da construção, e produz um pacote de aplicação que é adequado para ser servido sobre um serviço de hospedagem estática. Consultar o Implementando uma Aplicação Estática por orientações sobre os serviços populares.
Compatibilidade do Navegador
O pacote de produção pressupõe suporte para JavaScript moderno. Por padrão, a Vite dirige-se aos navegadores que suportam os módulos de ECMAScript nativo, importação dinâmica de Módulo de ECMAScript nativo, e import.meta
:
- Chrome >=87
- Firefox >=78
- Safari >=14
- Edge >=88
Nós podemos especificar alvos personalizados através da opção de configuração build.target
, onde o alvo inferior é es2015
.
Nota que por padrão, a Vite apenas manipula os transformações de sintaxe e não cobre os tapa-buracos de funcionalidades. Nós podemos consultar Polyfill.io que é um serviço que gera automaticamente pacotes de tapa-buracos baseado na sequência de caracteres do UserAgent
do navegador do utilizador.
Os navegadores antigos podem ser suportados através do @vitejs/plugin-legacy
, que gerará os pedaços para os navegadores antigos e tapa-buracos de funcionalidade da linguagem do ECMAScript correspondente. Os pedaços para os navegadores antigos são carregados condicionalmente apenas nos navegadores que não tem suporte ao Módulo de ECMAScript nativo.
Caminho de Base Pública
- Relacionado com: Manipulação de Recurso
Se estivermos implementando o nosso projeto em produção sob um caminho público encaixado, simplesmente especificamos a opção de configuração base
e todos os caminhos do recurso serão reescritos em conformidade. Esta opção também pode ser especificada como um sinal da linha de comando, por exemplo, vite build --base=/my/public/path/
.
As URLs do recurso importado da JavaScript, as referências da url()
da CSS, e as referências do recurso nos nossos ficheiros .html
são todos automaticamente ajustados para respeitarem esta opção durante a construção.
A exceção é quando precisamos concatenar dinamicamente as URLs em tempo real. Neste caso, podemos usar a variável import.meta.env.BASE_URL
injetado globalmente que será o caminho de base pública. Nota que esta variável é substituída estaticamente durante a construção, então deve aparecer exatamente como está (isto é, import.meta.env['BASE_URL']
não funcionará).
Para controlo avançado do caminho de base, consultar as Opções Avançadas da Base.
Personalizando a Construção
A construção pode ser personalizada através de várias opções de configuração da construção. Especificamente, podes diretamente ajustar as Opções de Rollup subjacentes através da build.rollupOptions
:
// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
// https://rollupjs.org/configuration-options/
}
}
})
// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
// https://rollupjs.org/configuration-options/
}
}
})
Por exemplo, podes especificar várias saídas de Rollup com extensões que apenas são aplicadas durante a construção.
Estratégia de Fatiamento
Tu podes configurar como os pedaços são separados utilizando a build.rollupOptions.output.manualChunks
(consulte a documentação da Rollup). Até a Vite 2.8, a estratégia de fatiamento padrão dividia os pedaços em index
e vendor
. É uma boa estratégia para algumas Aplicações de Página Única, mas é difícil fornecer uma solução geral para todos casos de uso alvos da Vite. Desde a Vite 2.9, manualChunks
já não modificado por padrão. Tu podes continuar a utilizar a estratégia de Separação Ambulante de Pedaço adicionando a splitVendorChunkPlugin
no teu ficheiro de configuração:
// vite.config.js
import { splitVendorChunkPlugin } from 'vite'
export default defineConfig({
plugins: [splitVendorChunkPlugin()]
})
// vite.config.js
import { splitVendorChunkPlugin } from 'vite'
export default defineConfig({
plugins: [splitVendorChunkPlugin()]
})
Esta estratégia também é fornecida como uma fábrica splitVendorChunk({ cache: SplitVendorChunkCache })
, neste caso a composição com lógica personalizada se faz necessária. A cache.reset()
precisa ser chamada no buildStart
para o modo de observação da construção para funcionar corretamente neste caso.
AVISO
Tu deves usar a forma da função build.rollupOptions.output.manualChunks
quando usares esta extensão. Se a forma do objeto for usada, a extensão não surtirá nenhum efeito.
Reconstrução Sobre Mudanças de Ficheiros
Tu podes ativar o observador de Rollup com vite build --watch
. Ou, podes diretamente ajustar a WatcherOptions
subjacente através da build.watch
:
// vite.config.js
export default defineConfig({
build: {
watch: {
// https://rollupjs.org/configuration-options/#watch
}
}
})
// vite.config.js
export default defineConfig({
build: {
watch: {
// https://rollupjs.org/configuration-options/#watch
}
}
})
Com a bandeira --watch
ativada, mudanças para a vite.config.js
, bem como para quaisquer ficheiros à serem empacotados, acionarão uma reconstrução.
Aplicação de Várias Páginas
Suponha que tens a seguinte estrutura de código-fonte:
├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
├── index.html
└── nested.js
├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
├── index.html
└── nested.js
Durante o desenvolvimento, apenas navegar ou ligar ao /nested/
- funciona como esperado, tal como para um servidor de ficheiro estático normal.
Durante a construção, tudo que precisas fazer é especificar vários ficheiros .html
como pontos de entrada:
// vite.config.js
import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
nested: resolve(__dirname, 'nested/index.html')
}
}
}
})
// vite.config.js
import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
nested: resolve(__dirname, 'nested/index.html')
}
}
}
})
Se especificares uma raiz diferente, lembra-te de que __dirname
ainda será a pasta do teu ficheiro vite.config.js
quando estiveres resolvendo os caminhos de entrada. Portanto, precisarás adicionar a tua entrada root
aos argumentos para a resolve
.
Nota que para os ficheiros de HTML, a Vite ignora o nome dado para a entrada no objeto rollupOptions.input
e ao invés disto respeita o identificador resolvido da ficheiro quando gera o recurso de HTML na pasta de distribuição. Isto garante uma estrutura consistente com a maneira que o servidor de desenvolvimento funciona.
Modo de Biblioteca
Quando estiveres desenvolvendo uma biblioteca orientada a navegador, estás provavelmente gastando a maior parte do tempo sobre a página de teste ou demonstração que importa a tua biblioteca real. Com a Vite, podes utilizar o teu index.html
para aquele propósito de obter a agradável experiência de programação.
Quando for o momento de empacotar a tua biblioteca para distribuição, utilizar a opção de configuração build.lib
. Certifica-te de também expor quaisquer dependências que não quiseres empacotar na tua biblioteca, por exemplo, vue
ou react
:
// vite.config.js
import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
// Também poderia ser um diretório ou
// arranjo de vários pontos de entrada
entry: resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
// as extensões apropriadas serão adicionadas
fileName: 'my-lib'
},
rollupOptions: {
// certifica-te de expor as dependências que não devem
// ser empacotadas na tua biblioteca
external: ['vue'],
output: {
// Forneça as variáveis globais para utilizar na
// construção UMD para as dependências expostas
globals: {
vue: 'Vue'
}
}
}
}
})
// vite.config.js
import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
// Também poderia ser um diretório ou
// arranjo de vários pontos de entrada
entry: resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
// as extensões apropriadas serão adicionadas
fileName: 'my-lib'
},
rollupOptions: {
// certifica-te de expor as dependências que não devem
// ser empacotadas na tua biblioteca
external: ['vue'],
output: {
// Forneça as variáveis globais para utilizar na
// construção UMD para as dependências expostas
globals: {
vue: 'Vue'
}
}
}
}
})
O ficheiro de entrada conteria exportações que poderiam ser importadas pelos utilizadores do teu pacote:
// lib/main.js
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export { Foo, Bar }
// lib/main.js
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export { Foo, Bar }
A execução de vite build
com esta configuração utiliza uma programação de Rollup que está orientada para entregar as bibliotecas e produzir dois formatos de pacote: es
e umd
(configurável através de build.lib
):
$ vite build
building for production...
dist/my-lib.js 0.08 kB / gzip: 0.07 kB
dist/my-lib.umd.cjs 0.30 kB / gzip: 0.16 kB
$ vite build
building for production...
dist/my-lib.js 0.08 kB / gzip: 0.07 kB
dist/my-lib.umd.cjs 0.30 kB / gzip: 0.16 kB
O package.json
recomendado para a tua biblioteca:
{
"name": "my-lib",
"type": "module",
"files": ["dist"],
"main": "./dist/my-lib.umd.cjs",
"module": "./dist/my-lib.js",
"exports": {
".": {
"import": "./dist/my-lib.js",
"require": "./dist/my-lib.umd.cjs"
}
}
}
{
"name": "my-lib",
"type": "module",
"files": ["dist"],
"main": "./dist/my-lib.umd.cjs",
"module": "./dist/my-lib.js",
"exports": {
".": {
"import": "./dist/my-lib.js",
"require": "./dist/my-lib.umd.cjs"
}
}
}
Ou, se estiveres expondo vários pontos de entrada:
{
"name": "my-lib",
"type": "module",
"files": ["dist"],
"main": "./dist/my-lib.cjs",
"module": "./dist/my-lib.js",
"exports": {
".": {
"import": "./dist/my-lib.js",
"require": "./dist/my-lib.cjs"
},
"./secondary": {
"import": "./dist/secondary.js",
"require": "./dist/secondary.cjs"
}
}
}
{
"name": "my-lib",
"type": "module",
"files": ["dist"],
"main": "./dist/my-lib.cjs",
"module": "./dist/my-lib.js",
"exports": {
".": {
"import": "./dist/my-lib.js",
"require": "./dist/my-lib.cjs"
},
"./secondary": {
"import": "./dist/secondary.js",
"require": "./dist/secondary.cjs"
}
}
}
Extensões de Ficheiro
Se o package.json
não conter a "type": "module"
, a Vite gerará extensões de ficheiro diferentes para compatibilidade da Node.js. A .js
tornar-se-á em .mjs
e .cjs
tornar-se-á em .js
.
Variáveis de Ambiente
No modo de biblioteca, todas as utilizações de import.meta.env.*
são substituídas estaticamente quando estiveres construindo para produção. No entanto, as utilizações de process.env.*
não são, para que os consumidores da tua biblioteca possam mudá-la dinamicamente. Se isto for indesejável, podes utilizar a define: { 'process.env.
NODE_ENV': '"production"' }
por exemplo para substituí-las estaticamente.
Uso Avançado
O modo de biblioteca inclui uma simples e opiniosa configuração para bibliotecas orientadas para o navegador e para abstração de JavaScript. Se estivermos a construir bibliotecas que não estão destinadas ao navegador, ou exigem fluxos de construção avançados, podemos usar diretamente a Rollup ou esbuild.
Opções de Base Avançada
AVISO
Esta funcionalidade é experimental. Comente.
Para casos de usos avançados, os recursos desdobrados e ficheiros públicos podem estar caminhos diferentes, por exemplo para utilizares diferentes estratégias de cache. Um utilizador pode escolher desdobrar em três caminhos diferentes:
- Os ficheiros de HTML de entrada gerados (os quais podem ser processados durante a SSR)
- O recursos embaralhados gerados (JS, CSS, e outros tipos de ficheiros como imagens)
- Os ficheiros públicos copiados
Uma única base estática não é o suficiente nestes cenários. A Vite fornece suporte experimental para opções de base avançada durante a construção, utilizando a experimental.renderBuiltUrl
.
experimental: {
renderBuiltUrl(filename: string, { hostType }: { hostType: 'js' | 'css' | 'html' }) {
if (hostType === 'js') {
return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` }
} else {
return { relative: true }
}
}
}
experimental: {
renderBuiltUrl(filename: string, { hostType }: { hostType: 'js' | 'css' | 'html' }) {
if (hostType === 'js') {
return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` }
} else {
return { relative: true }
}
}
}
Se os recursos embaralhados e ficheiros públicos não forem desdobrados juntos, as opções para cada grupo podem ser definidas de maneira independente utilizando a type
de recurso incluído no segundo parâmetro de context
dado para função.
experimental: {
renderBuiltUrl(filename: string, { hostId, hostType, type }: { hostId: string, hostType: 'js' | 'css' | 'html', type: 'public' | 'asset' }) {
if (type === 'public') {
return 'https://www.domain.com/' + filename
}
else if (path.extname(hostId) === '.js') {
return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` }
}
else {
return 'https://cdn.domain.com/assets/' + filename
}
}
}
experimental: {
renderBuiltUrl(filename: string, { hostId, hostType, type }: { hostId: string, hostType: 'js' | 'css' | 'html', type: 'public' | 'asset' }) {
if (type === 'public') {
return 'https://www.domain.com/' + filename
}
else if (path.extname(hostId) === '.js') {
return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` }
}
else {
return 'https://cdn.domain.com/assets/' + filename
}
}
}