Две недели назад (202.02.17),выпущен vit2.0vite 2.0, как интерфейсный инструмент следующего поколения, использующий собственный ESM браузера, является более зрелым, чем 1.0. До этого я началОбратите внимание на такого рода «новые» интерфейсные инструменты.. На этот раз, воспользовавшись выпуском vite 2.0, существующий проект на основе vue-cli(-service) + vue2 был успешно перенесен.
Миграция прошла гладко и заняла менее половины дня. Тем не менее, в течение всего процесса миграции также возникали небольшие проблемы, которые кратко изложены здесь, чтобы облегчить общение и рекомендации для друзей, столкнувшихся с похожими проблемами.
Предыстория проекта
Прежде чем представить конкретную работу по миграции, сначала кратко расскажите о ситуации с проектом. В настоящее время проект запущен менее чем за год, и долгов по наследству, связанных со строительством, не так уж и много. Проект содержит 1897 файлов модулей (включая модули в node_modules), использует стек технологий vue2 + vuex + typescript, а инструмент сборки использует vue-cli (webpack). Это относительно стандартный стек технологий vue. Поскольку это внутренняя система, у проекта более низкие требования к совместимости, и пользователи в основном используют более новый браузер Chrome (некоторые используют Safari).
Миграционная работа
Ниже приводится подробное описание того, какая обработка была выполнена при миграции.
1. Файл конфигурации
Сначала вам нужно установить vite и создать файл конфигурации vite.
npm i -D vite
Используется в сервисе vue-clivue.config.js
В качестве файла конфигурации; по умолчанию vite необходимо создатьvite.config.ts
как файл конфигурации. Базовый файл конфигурации прост:
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
// ...
],
})
Создайте этот файл конфигурации, и предыдущий файл vue.config.js больше не будет использоваться.
2. Запись и файл HTML
Файл записи также необходимо указать в vite. Но в отличие от webpack, в vite вместо указания js/ts в качестве точки входа в качестве точки входа указывается фактический HTML-файл.
В веб-пакете пользователи делают это, устанавливая запись в запись js (например,src/app.js
), чтобы указать файл ввода для упаковки js, дополненный HtmlWebpackPlugin для внедрения сгенерированного пути к файлу js в HTML. И vite использует файл HTML напрямую, он будет анализировать тег скрипта в HTML, чтобы найти файл записи js.
Поэтому мы включаем ссылку тега скрипта на файл js/ts в запись HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
</noscript>
<div id="app"></div>
+ <script type="module" src="/src/main.ts"></script>
</body>
</html>
Обратите внимание на приведенное выше<script type="module" src="/src/main.ts"></script>
Эта строка, которая использует собственный ESM браузера для загрузки скрипта,/src/main.ts
Это исходное местоположение записи js. Когда запускается режим vite dev, он фактически запускает сервер, аналогичный статическому серверу, и обслуживает каталог исходного кода, поэтому нет необходимости в сложном процессе упаковки модулей, таком как веб-пакет. Загрузка зависимостей модуля будет полностью зависеть от браузера.import
Обработка синтаксиса, поэтому вы можете увидеть длинный список каскадов загрузки скриптов:
Обратите внимание и здесьКорневые настройки проекта. По умолчанию этоprocess.cwd()
, а index.html также ищется в корне проекта. Для удобства буду./public/index.html
переехал в./index.html
.
3. Используйте плагин vue
vite 2.0 обеспечивает хорошую поддержку проектов vue, но не сильно связан с vue, поэтому поддерживает создание проектов стека технологий vue в виде подключаемых модулей. Подключаемый модуль vue, рекомендуемый в настоящее время на официальном веб-сайте vite 2.0 (2021.2.28), будетSFC для vue3Лучше использовать вместе. Поэтому здесь используется плагин, предназначенный для поддержки vue2.vite-plugin-vue2, поддерживает JSX, а последняя версия такжеподдержка vit2.
Он также очень прост в использовании:
import { defineConfig } from 'vite';
+ import { createVuePlugin } from 'vite-plugin-vue2';
export default defineConfig({
plugins: [
+ createVuePlugin(),
],
});
4. Отображение путей машинописного текста
При создании проекта ts с помощью vite, если вы используетесопоставление путей машинописного текстафункция, требуется специальная обработка, иначе будет ошибка, что модуль не может быть разрешен (не может быть найден):
Здесь нужно использоватьvite-tsconfig-pathsЭтот плагин выполняет синтаксический анализ и замену сопоставлений путей. Принцип относительно прост, примерно плагин viteловушка идентификатора разрешенияэтап, используяtsconfig-pathsЭта библиотека для преобразования сопоставлений путей в фактические возвращенные сопоставления. Если вам интересно, вы можете посмотреть на реализацию этого плагина, которая относительно краткая.
Конкретное использование заключается в следующем:
import { defineConfig } from 'vite';
import { createVuePlugin } from 'vite-plugin-vue2';
+ import tsconfigPaths from 'vite-tsconfig-paths';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
createVuePlugin(),
+ tsconfigPaths(),
],
});
5. Замените CommonJS
vite использует ESM как модульное решение, поэтому его использование не поддерживается.require
способ импорта модулей. В противном случае он сообщит во время выполненияUncaught ReferenceError: require is not defined
ошибка (браузер не поддерживает CJS, естественно инъекция метода не требуется).
Кроме того, могут возникнуть проблемы совместимости с ESM и CJS. Конечно, это не проблема со сборкой vite, но об этом нужно знать. Проще говоря, в ESM есть понятие по умолчанию, а в CJS — нет. Любая экспортируемая переменная рассматривается CJS как свойство объекта module.exports, а экспорт ESM по умолчанию — это просто свойство module.exports.default объекта cjs. Например, в typescript мы будем использовать конфигурацию esModuleInterop, чтобы позволить tsc добавить некоторый совместимый код, помогающий разрешать импортированные модули, и аналогичные операции есть в webpack.
Например, предыдущий код:
module.exports = {
SSO_LOGIN_URL: 'https://xxx.yyy.com',
SSO_LOGOUT_URL: 'https://xxx.yyy.com/cas/logout',
}
const config = require('./config');
И экспорт, и импорт необходимо изменить на ESM, например:
export default {
SSO_LOGIN_URL: 'https://xxx.yyy.com',
SSO_LOGOUT_URL: 'https://xxx.yyy.com/cas/logout',
}
import config from './config';
6. Как использовать переменные окружения
При использовании vue-cli (webpack) мы часто используем переменные среды для оценки кода во время выполнения, например:
const REPORTER_HOST = process.env.REPORTER_TYPE === 'mock'
? 'http://mock-report.xxx.com'
: 'http://report.xxx.com';
vite по-прежнему поддерживает переменные средыиспользуется, но больше не доступенprocess.env
такой доступ. но нужно пройтиimport.meta.env
для доступа к переменным среды:
-const REPORTER_HOST = process.env.REPORTER_TYPE === 'mock'
+const REPORTER_HOST = import.meta.env.REPORTER_TYPE === 'mock'
? 'http://mock-report.xxx.com'
: 'http://report.xxx.com';
Подобно веб-пакету, vite такжеНекоторые переменные окружения встроены, можно использовать напрямую.
7.import.meta.env
types
Дополнение: vite предоставляет необходимые ему определения типов, которые можно применять напрямуюvite/clientЧтобы представить, вы можете добавить его самостоятельно без следующих методов.
Если вы передаете машинописный текстimport.meta.env
Для доступа к переменным среды может появиться сообщение об ошибке ts:类型“ImportMeta”上不存在属性“env”
.
Это связано с тем, что в текущей версии (v4.2.2)import.meta
Определение по-прежнемупустой интерфейс:
interface ImportMeta {
}
Но мы можем дополнительно определить тип ImportMeta в проекте с помощью возможности слияния интерфейса, чтобы расширитьimport.meta.env
поддержка типа. Например, проект ts, ранее сгенерированный vue-cli, будет сгенерирован в каталоге src.vue-shims.d.ts
файл, вы можете расширить поддержку типа env здесь:
declare global {
interface ImportMeta {
env: Record<string, unknown>;
}
}
Таким образом, вы не получите ошибку.
8. веб-пакет требует контекста
В вебпаке мы можем передатьrequire.context
Метод разрешает модуль «динамически». Обычной практикой является указание каталога и загрузка некоторых модулей через обычное сопоставление, чтобы после добавления новых модулей можно было добиться эффекта «динамического автоматического импорта».
Например, в проекте мы динамически сопоставляем файл route.ts в папке modules и задаем конфигурацию роутера в глобальном vue-router:
const routes = require.context('./modules', true, /([\w\d-]+)\/routes\.ts/)
.keys()
.map(id => context(id))
.map(mod => mod.__esModule ? mod.default : mod)
.reduce((pre, list) => [...pre, ...list], []);
export default new VueRouter({ routes });
Структура файла следующая:
src/modules
├── admin
│ ├── pages
│ └── routes.ts
├── alert
│ ├── components
│ ├── pages
│ ├── routes.ts
│ ├── store.ts
│ └── utils
├── environment
│ ├── store
│ ├── types
│ └── utils
└── service
├── assets
├── pages
├── routes.ts
├── store
└── types
require context — это уникальный модульный метод, предоставляемый webpack, а не языковой стандарт, поэтому require context больше нельзя использовать в vite. Однако если его полностью изменить на ручной импорт модулей разработчиками, то, во-первых, изменения в существующем коде легко приведут к пропускам импорта модулей, во-вторых, от этого «гибкого» механизма придется отказаться, а последующие режимы разработки также будут изменены на некоторые степень. К счастью, vite2.0 предоставляетИмпорт модулей для шаблонов глобусов. Эта функция может достичь вышеуказанных целей. Конечно, потребуются некоторые изменения кода:
const routesModules = import.meta.globEager<{default: unknown[]}>('./modules/**/routes.ts');
const routes = Object
.keys(routesModules)
.reduce<any[]>((pre, k) => [...pre, ...routesMod[k].default], []);
export default new VueRouter({ routes });
в основном дляrequire.context
изменить наimport.meta.globEager
, адаптируя тип возвращаемого значения. Конечно, для поддержки типов можно добавить некоторые типы в интерфейс ImportMeta:
declare global {
interface ImportMeta {
env: Record<string, unknown>;
+ globEager<T = unknown>(globPath: string): Record<string, T>;
}
}
Кроме того, упомяните это снова,import.meta.globEager
Выполнит статический анализ во время сборки, чтобы заменить код статическими операторами импорта. Если вы хотите поддерживать динамический импорт, используйтеimport.meta.glob
метод.
9. API-прокси
vite2.0 по-прежнему предоставляет HTTP-сервер во время локальной разработки (режим DEV), а также поддерживаетУстановить прокси через пункт прокси. Он также используется за тем же, что и webpackhttp-proxy, поэтому настройки прокси для vue-cli можно перенести на vite:
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
import { createVuePlugin } from 'vite-plugin-vue2';
+ import proxy from './src/tangram/proxy-table';
export default defineConfig({
plugins: [
tsconfigPaths(),
createVuePlugin(),
],
+ server: {
+ proxy,
+ }
});
10. Вставка HTML-контента
На основе vue-cli мы можем использовать HtmlWebpackPlugin веб-пакета для замены значений в HTML, например<%= htmlWebpackPlugin.options.title %>
Эта форма заменяет переменную шаблона во время компиляции фактическим значением заголовка. Также очень просто реализовать такую функцию, напримерvite-plugin-html. Этот плагин реализует внедрение переменных шаблона на основе ejs черезtransformIndexHtml
Хук, который получает необработанную строку HTML, затем отображает введенные переменные через ejs и возвращает.
Ниже приведен метод настройки с использованием vite-plugin-html после миграции:
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
import { createVuePlugin } from 'vite-plugin-vue2';
+ import { injectHtml } from 'vite-plugin-html';
export default defineConfig({
plugins: [
tsconfigPaths(),
createVuePlugin(),
+ injectHtml({
+ injectData: {
+ title: '用户管理系统',
+ },
}),
],
server: {
proxy,
},
});
Измените запись переменной шаблона HTML в соответствии с соответствующими требованиями:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
- <title><%= htmlWebpackPlugin.options.title %></title>
+ <title><%= title %></title>
</head>
<body>
<noscript>
- We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
+ We're sorry but <%= title %> doesn't work properly without JavaScript enabled.
</noscript>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
11. Обработка совместимости
В вводной информации о проекте упоминается, что у проекта очень низкие требования к совместимости, поэтому эта часть фактически не участвует в миграции.
Конечно, если есть проекты, требующие совместимости, можно использовать@vitejs/plugin-legacyплагин. Плагин упаковывает два набора кода, один для современных браузеров и один для старых браузеров с различными полифиллами и совместимостью синтаксиса. Также используйте в HTMLмодульная/номодульная технологияреализовать "условную загрузку" в новых/старых браузерах.
Суммировать
В проекте содержится 1897 файлов модулей (включая модули в node_modules), а время сборки до и после миграции (без кеша) следующее:
vue-cli | vite 2 | |
---|---|---|
режим разработки | ~8s | ~400ms |
рабочий режим | ~42s | ~36s |
Можно видеть, что эффективность конструкции vite2 значительно повышается в режиме DEV. Это также связано с тем, что в режиме DEV выполняется только небольшая обработка файла модуля и не выполняется тяжелая работа по упаковке. используйте esbuild и rollup для сборки, поэтому повышение эффективности в этом проекте не очевидно.
Выше перечислены некоторые проблемы, с которыми столкнулся автор при переносе vite 2.0 с vue-cli. Все они являются относительно небольшими точками, и в целом миграция не встретила особых препятствий, и мигрировала менее чем за полдня. Конечно, это также зависит от работы по стандартизации JavaScript и HTML в последние годы, так что основной код, который мы пишем, также может иметь определенное единообразие. Это также одно из больших преимуществ, которые эти интерфейсные инструменты приносят нам в программирование, ориентированное на будущее. Я надеюсь, что эта статья может дать ссылку друзьям, которые собираются попытаться перейти на vite 2.0.