Авторы этой статьи: Wind, Skyler, ZRJ, ZJ
предисловие
Webpack5 был официально выпущен 10 октября 2020 г., и за последние несколько месяцев он быстро развивался и обновлялся.По состоянию на 28 января Webpack5 был обновлен 18 второстепенными версиями, что принесло много очень привлекательных новых функций. согласно сВведение на официальном сайте, общие направленные изменения Webpack5 выглядят следующим образом:
- Повысьте производительность сборки с помощью возможностей постоянного кэширования диска
- Улучшите долгосрочное кэширование с помощью лучших алгоритмов (уменьшите количество промахов кэша для ресурсов продукта).
- Оптимизируйте размер продукта с помощью улучшенных возможностей Tree Shake и логики генерации кода.
- Улучшить совместимость с веб-платформой
- Убрано некоторое странное состояние во внутренней структуре, которое осталось, когда Webpack4 представил некоторые новые функции без серьезного обновления.
- Внеся некоторые серьезные изменения для подготовки к некоторым будущим функциям, он может быть стабильным в версии Webpack5 в течение длительного времени.
Последние два пункта являются относительно абстрактными, но в целом видно, что на самом деле для разработчиков, обновляющих Webpack5, они могут заметить, что эффективность построения и производительность среды выполнения были значительно улучшены, включая некоторые новые функции, которые могут дать нам более удобную «позу кодирования».
командная практика
В настоящее время команда использует Webpack4 для создания всей системы сборки.При миграции мы обращаемся к официальному веб-сайту, предоставленному Webpack.Руководство по обновлению, здесь мы интегрируем некоторые моменты, имеющие практическую ценность для нашего бизнеса на текущем этапе (новые функции в основном имеют реальную пользу), интегрированные в процесс строительства команды, проверенные и записанные на практике и зафиксировавшие процесс, с которым мы столкнулись в процессе строительства инфраструктуры Некоторые проблемы и обходные пути.
Готов к работе
Предварительное расследование
Прежде всего, с помощью рекомендаций, данных официальными документами, мы можем найти некоторые места, которые явно необходимо изменить, включая следующие аспекты:
- Webpack5 требует поддержки Node версии ^10.13.0. При локальном использовании вам необходимо обновить версию Node до 10.13.0 или выше. При использовании некоторых инструментов CI для создания продуктов также необходимо синхронно обновить соответствующий образ или версию Node, настроенную на CI.
- Плагин html-webpack в проекте необходимо обновить доВерсии, поддерживающие Webpack5
- Используемый в проекте плагин workbox-webpack-plugin необходимо обновить до версии, поддерживающей Webpack5.
- DevServer необходимо обновить webpack-dev-server до ^4 (следующей) версии, иначе HMR будет ненормальным.
- Webpack5 удаляет Node.js Polyfill, из-за чего некоторые пакеты становятся недоступными (что будет выводиться в консоли
'XXX' is not defined
), При желании другой совместимый процесс Nodejs Polyfill придется установить соответствующий Polyfill: процесс, инъекцию и явно объявленный в плагине
// webpack.config.js
{
...,
plugins: [
...,
new webpack.ProvidePlugin({
process: 'process/browser',
}),
]
}
-
Если вы столкнулись с некоторыми предупреждениями об устаревании API при использовании Webpack5, вы можете решительно поискать в Google.Как правило, вы можете полностью решить проблему, обновив некоторые плагины, и эти предупреждения не окажут никакого влияния на вашу сборку на данном этапе.Деструктивные эффекты, ниже мы приведите несколько ссылок на осадки в нашей практике:
-
Предупреждения, которые можно устранить, обновив terser-webpack-plugin:
-
Compilation.cache was removed
-
optimizeChunkAssets
-
-
Предупреждения, которые можно устранить путем обновления плагина mini-css-extract:
-
MainTemplate.hooks.renderManifest
-
ChunkTemplate.hooks.renderManifest
-
MainTemplate.hooks.hashForChunk
-
Module.id: Use new ChunkGraph API
-
Module.updateHash
-
Chunk.modulesIterable
-
MainTemplate.outputOptions
-
MainTemplate.renderCurrentHashCode
-
MainTemplate.getAssetPath
-
MainTemplate.requireFn
-
ChunkGroup.getModuleIndex2 was renamed to getModulePostOrderIndex
-
-
Сделав предыдущие приготовления, мы можем напрямую обновить шаттл:
npm install webpack@latest --dev
Затем вы можете начать пробовать захватывающий Webpack5~
Дневник наступления на яму
Экологичный Webpack5
Если ваш проект обновлен до WebPack5, запустите сборку или deVServer в проекте, вы обычно получаете сообщение об ошибке, подобное следующему:
TypeError: Cannot add property htmlWebpackPluginAlterChunks, object is not extensible
at /path/to/node_modules/html-webpack-plugin/index.js:59:56
Если вы старый драйвер Webpack, вы должны найти ключ к этой проблеме с первого взгляда -html-webpack-plugin
, откройте плагинГитхаб Главная, решение перед вами:
Точно так же, если в консоли выдается ошибка или предупреждение, большинство проблем можно решить, обновив версию соответствующих зависимостей.Обновление Webpack 5 по-прежнему намного более плавное, чем обновление Webpack 4 в прошлом. , и экология в сообществе тоже постепенно улучшается. Следите и дорабатывайте.
Вот еще несколько распространенных примеров, таких как workbox-webpack-plugin, который мы часто используем для поддержки serviceWorker, поскольку он также зависит от основных событий Webpack и некоторых API, поэтому его также необходимо обновить. к:GitHub.com/Google CHROM…CSSoptimize-css-assets-webpack-plugin, на домашней странице Plugin Github также четко указано, что после Webpack5 в первую очередь будет использоваться официальный сайт Webpack.css-minimizer-webpack-plugin.
Конечно, есть некоторые другие экологические аспекты, которые не будут повторяться в этом документе.Большую часть содержания можно найти в двух официальных документах, вступлении на официальный веб-сайт и в руководстве по обновлению, Кейс Для решения общих проблем большая часть сообщества уже нашла подсказки в задачах или других документах.Конечно, если вы обнаружите какие-то проблемы, требующие решения, разве это не возможность для вас внести свой вклад в открытое исходное сообщество~
После основного обновления вышеперечисленных зависимостей ваш проект может работать через Webpack5.
P.S. Плагин optimise-css-assets-webpack-plugin не имеет ни кеша, ни параллелизма, я бы предпочёл использовать cssnano в загрузчике для оптимизации логики CSS, чем тратить свою жизнь на этот плагин 🤫, но css- Minimizer-webpack-plugin спас меня от обсессивно-компульсивного расстройства, это действительно лучший выбор.
HMR, который зависает при касании
Так как webpack-dev-server опирается на множество конфигураций сборки Webpack, то после апгрейда в некоторых местах не так гладко, как с заземлением.HMR самый яркий пример, он становится очень хрупким, часто по незнанию, вы вдруг обнаружите, что эта штука не отвечает? !
Моим первым побуждением было подумать, что я упустил какую-то конфигурацию devServer, но разве я не следовал официальному документу CV? ! Успокоившись, я нажал на Google, и, конечно же, кто-то в сообществе уже встречался раньшетот же вопрос.
Я сделаю длинную историю короткой здесь, этоwebpack-dev-server
Наследие ОШИБКИ, только вы в конфигурации Webpack явно установилиtarget: 'web'
HMR может вступить в силу, даже если вы устанавливаете цель через массив, например:target: \['web', 'es5'\]
, что также блокирует способность HMR.
Но, к счастью, официальный выпуск версии v4 Webpack5, вам нужно только обновить webpack-dev-server до следующей версии (если вы используете его в проекте через Node API, который он предоставляет), вы можете решить вышеуказанные проблемы:
Однако по состоянию на 28 января 2020 г. webpack-dev-server v4Выпущена только бета0 следующая версия, поэтому некоторые способности нестабильны, напримерВы не можете запустить свой проект с локального хоста, но это всего лишь детали, не влияющие на общий функционал.
Что нового во время сборки
Встроенная возможность создания статических ресурсов — модули активов
Webpack будет упаковывать только файлы JS, если вы хотите упаковать другие файлы, вам нужно добавить соответствующий загрузчик.
До Webpack5 мы обычно использовали следующие загрузчики для обработки некоторых распространенных статических ресурсов, таких как изображения PNG, значки SVG и т. д. Их окончательные эффекты примерно следующие:
- raw-loader: позволяет обрабатывать файлы как строковый импорт
- загрузчик файлов: упакуйте и экспортируйте файл в выходной каталог и верните URI файла при импорте
- url-loader: когда размер файла достигает определенного требования, он может быть обработан в URIS base64, встроенный загрузчик файлов
Webpack5 предоставляет встроенные возможности создания статических ресурсов. Нам не нужно устанавливать дополнительные загрузчики. Нам нужна только простая конфигурация для реализации упаковки и хранения статических ресурсов в подкаталогах. А именно: ресурсы, соответствующие правилу соответствия, могут храниться в папке активов.
// webpack.config.js
module.exports = {
...,
module: {
rules: [
{
test: /\.(png|jpg|svg|gif)$/,
type: 'asset/resource',
generator: {
// [ext]前面自带"."
filename: 'assets/[hash:8].[name][ext]',
},
},
],
},
}
Значение типа следующее:
- актив/источник — Функционально эквивалентен необработанному загрузчику.
- актив/встроенный - функция эквивалентна url-loader.Если вы хотите установить правила кодирования, вы можете установить dataUrl в генераторе. Подробнее см.официальная документация.
- актив/ресурс - функционально эквивалентен файловому загрузчику. Ресурсы в проекте упакованы таким образом, благодаря тому, что в командном проекте полностью использованы соответствующие возможности HTTP2-мультиплексирования, мы можем единообразно обрабатывать ресурсы в виде файлов, и разрешить их параллельную передачу при они приобретаются. , чтобы избежать встроенного в js файл в виде кодировки, что вызовет увеличение объема ресурса и повлияет на загрузку ресурса.
- актив - тип по умолчанию будет выбран в соответствии с размером файла.Когда размер файла меньше 8 КБ, будет использоваться актив/встроенный, в противном случае будет использоваться актив/ресурс. Порог также можно установить вручную.Подробнее см.официальная документация.
Встроенная возможность кэширования файловой системы для ускорения вторичного построения
До Webpack5 мы использовалиcache-loaderКэшируйте некоторые загрузчики с высокой производительностью или используйтеhard-source-webpack-pluginОбеспечить некоторый промежуточный кеш для модулей. После Webpack5 встроенная возможность кэширования интегрирована у нас по умолчанию (Кэшировать модули и чанки). С помощью следующей конфигурации вы можете ускорить вторую сборку.
// webpack.config.js
module.exports = {
...,
cache: {
type: 'filesystem',
// 可选配置
buildDependencies: {
config: [__filename], // 当构建依赖的config文件(通过 require 依赖)内容发生变化时,缓存失效
},
name: '', // 配置以name为隔离,创建不同的缓存文件,如生成PC或mobile不同的配置缓存
...,
},
}
Каталог хранилища кэша по умолчанию в производственной среде находится вnode_modules/.cache/webpack/default-production
Если вы хотите изменить его, вы можете настроить имя для секретного хранилища. активname: 'production-cache'
Место хранения сгенерированного кеша выглядит следующим образом.
PS: Если вы выполняете пользовательскую операцию сборки напрямую, вызывая метод run экземпляра компилятора Webpack, вы можете столкнуться сКэш сборки заканчивается тем, что не создает файлы кешаВ случае , после поиска связанных проблем Webpack, мы обнаружили, что вам также необходимо вручную вызватьcompiler.close()
для вывода файла кэша.
Встроенная компиляция WebAssembly и возможности асинхронной загрузки (синхронизация/асинхронность)
WebAssemblyОн разработан как веб-ориентированный файл двоичного формата, который ближе к машинному коду, имеет меньший размер файла и более высокую эффективность выполнения. Языки высокого уровня, такие как c/c++, могут быть напрямую скомпилированы в.wasm
Файл вызывается js. Сам Webpack4 интегрировал возможности загрузки WebAssembly, но в Webpack5 возможности асинхронной загрузки WebAssembly были расширены, что позволяет нам более гибко делать более интересные вещи с WebAssembly.
Пользуясь случаем, мы можем кратко представить процесс быстрого запуска WebAssembly в реальной разработке проекта:
Возьмите простую функцию суммирования в качестве примера, в дополнение к следующимофициальная документацияПомимо создания файлов WebAssembly, мы можем передатьWasmFiddleЭтот онлайн-URL используется для написания программ на c/c++, которые напрямую преобразуются в файлы WebAssembly, а веб-сайт также предоставляет нам возможности мгновенной отладки.
С помощью вышеуказанного метода мы можем быстро получить файл program.wasm, загрузить его в локальный проект, и вы можете начать его использовать.
До Webpack5 мы будем использовать wasm-loader для обработки файлов WebAssembly, и нам нужно использовать следующий пример кода для вызова функций, которые мы инкапсулировали в wasm:
import wasm from '/program.wasm';
wasm().then(instance => {
const sum = instance.exports.sum;
console.log(sum(1, 2));
}
Этот процесс обязательно будет повторяющимся и громоздким, но со встроенной возможностью сборки WebAssembly в Webpack5 нам нужно настроить только следующее:
// webpack.config.js
module.exports = {
...,
experiments: {
asyncWebAssembly: true,
},
module: {
rules: [
...,
{
test: /\.wasm$/,
type: 'webassembly/async',
},
],
},
}
И когда мы хотим использовать wasm, это так просто:
import { sum } from './program.wasm'
console.log(sum(1, 2))
Встроенные возможности построения Web Worker
Веб-воркеры предоставляют веб-содержимому простой способ запуска сценариев в фоновом потоке. Потоки могут выполнять задачи, не мешая пользовательскому интерфейсу. Обычно мы можем поместить некоторые более сложные алгоритмы, такие как шифрование и дешифрование или обработка изображений, в подпоток, а затем связаться с основным потоком после выполнения подпотока.
Предположим, у нас есть трудоемкая логика расчета, хранящаяся в файле calc.js, когда мы завершим выполнение, передаемpostMessage
Сообщите основному потоку информацию о файле.
// calc.worker.js
let num;
for (let i = 0; i <= 20000000; i++) {
if (i === 20000000) {
num = 20000000;
}
}
postMessage({
value: num,
});
Основной поток master.js прослушивает сообщения подпотоков и выполняет соответствующие операции при передаче сообщения.
// master.js
worker.onmessage = e => {
console.log(e.data.value);
};
В прошлом при работе с Web Worker нам нужна помощь worker-loader для работы со следующими конфигурациями.
// webpack.config.js
module.exports = {
...,
module: {
rules: [
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' },
},
],
},
}
При использовании объект Worker может быть создан путем прямого импорта файла calc.worker.js, поэтому основной поток обрабатывается следующим образом:
// master.js
import Worker from './calc.worker.js';
const worker = new Worker();
worker.onmessage = e => {
console.log(e.data.value);
};
В Webpack5 нам не нужно добавлять метод обработки загрузчика, и нам не нужно настраивать для воркера конкретное имя файла, например .worker.js.С помощью нового URL создание воркера можно осуществленный. Ниже вы также можете обратиться кОфициальный пример:
// master.js
const worker = new Worker(new URL('./calc.js', import.meta.url), {
name: "calc"
/* webpackEntryOptions: { filename: "workers/[name].js" } */
});
worker.onmessage = e => {
console.log(e.data.value);
};
Однако, по привычке разработчика и удобству для программирования, в этот раз мы не убрали весь worker-loader.import
Один.worker.js
суффикс для использования веб-воркеров; в то же время вы также можете использовать новые функции Webpack5 выше, ноОбратите внимание, что вnew URL()
нельзя использовать в.worker.js
Назовите файл, иначе он будет сначала проанализирован worker-loader, и ваш worker не будет работать должным образом..
новые функции времени выполнения
Node.js Polyfills удалены, Polyfills свободно контролируются разработчиками.
Поскольку Node.js Polyfills были удалены, если во внешнем пакете используются зависимости процесса и пути, поддержку Polyfill необходимо добавить вручную. Например, процесс, описанный в предыдущих приготовлениях и т. д.
Возьмем в качестве примера реакцию-уценку, когда наш проект будет обновлен до Webpack5, появится сообщение об ошибке.process.cwd is not a function
, если вы столкнулись с похожей ситуацией в проекте, например знакомыйnodejs APIОшибка в консолиis not defined
, в настоящее время нам нужно добавить соответствующий полифилл браузера самостоятельно, потому что Webpack5 больше не будет обрабатывать эти полифиллы за вас. Подробную настройку процесса см. в разделе «Подготовка».
Стратегия упаковки ресурсов лучше, а строительный продукт более «легкий».
Prepack — это инструмент оптимизации кода JavaScript с открытым исходным кодом от Facebook, который запускается на этапе «компиляции» и генерирует оптимизированный код. Ниже приведен пример на официальном сайте Prepack, Мы видим, что, когда функция может получить фиксированный вывод для любого ввода, Prepack может вычислить результат для нас во время компиляции. Для некоторой сложной и фиксированной вычислительной логики эта возможность «предварительного вычисления» может не только уменьшить размер нашего пакета, но и ускорить время выполнения. Такие какОфициальный примерпоказано:
Webpack5 имеет некоторые встроенные возможности Prepack, которые могут максимально оптимизировать объем продуктов вашего проекта:
Поддержка возможности глубокого встряхивания дерева
Возможность Tree Shaking относится к возможности удалять переменные, на которые нет ссылок в контексте JavaScript, во время процесса упаковки, тем самым уменьшая объем после упаковки. Например, когда мы внедряем файл на этапе разработки, в указанном файле есть какой-то неиспользуемый код, или мы забываем удалить его во время разработки, или код, оставленный предыдущим разработчиком, но делать это смело неудобно. работа по удалению, с функцией встряхивания дерева, это не будет проблемой.Webpack может автоматически помочь нам удалить неиспользуемый код при упаковке, особенно Webpack5 может поддерживать глубоко вложенный экспорт.Встряхивание дерева, для получения подробной информации см.Официальный сайтДан пример:
Взяв приведенный выше пример в качестве примера, с возможностями Webpack5 и возможностями, подобными Prepack, упомянутыми выше, эти избыточные коды автоматически удаляются:
Итак, вам все еще нужно беспокоиться о том, что в проекте будет избыточный код, который будет обременять размер вашего онлайн-пакета?
Более дружественная поддержка долгосрочного кэша, chunkid не изменился
До Webpack5 имена файлов после упаковки располагались в порядке их идентификатора.При последующем изменении файла имя упакованного файла будет изменено, даже если содержимое файла не изменилось. В результате кеш ресурса будет аннулирован.
Webpack5 имеет более удобную поддержку долгосрочного кэширования, вычисляет короткий цифровой идентификатор для упакованных модулей и фрагментов с помощью алгоритма генерации хэша, так что даже если определенный файл будет удален в середине, это не вызовет большого количества сбои файлового кэша. Подробнее см.Официальный сайт.
Например, мы добавляем в проект новую страницу, а затем сравниваем изменения в названиях продуктов после упаковки Webpack4 и Webpack5:
Webpack4: новый фрагмент, сгенерированный в первую очередь, сделает недействительным кеш всех js-файлов.Из содержимого исходной карты видно, что два JS-файла с совершенно разными именами всегда указывают на исходный файл.
Webpack5: недействителен только для измененных файлов
Здесь необходимо дополнительное расширение, и Webpack5 также используетнастоящий хеш контентаДля поддержки более дружественного долгосрочного кеша, что это значит?Если вы просто удалите комментарий или измените имя переменной в своей логике, ваша логика кода не изменится по существу, поэтому для сжатого файла изменения этого содержимого не приводят в contenthash изменения.
Поддержите на высшем уровне Подождите, попрощайтесь с асинхронностью с этого момента
Webpack5 также поддерживает ожидание верхнего уровня. Это позволяет разработчикам использовать поля ожидания вне асинхронных функций. Это похоже на гигантские асинхронные функции в том смысле, что модуль, импортирующий их, ждет, пока они начнут выполнять свой код, поэтому такой способ исключения асинхронности доступен только на верхнем уровне.
Включив следующую конфигурацию:
// webpack.config.js
module.exports = {
...,
experiments: {
topLevelAwait: true,
},
}
До и после сравнения возьмем в качестве примера логику словаря i18n pull, часто используемого в нашем проекте интернационализации:
// 开启 top level await 之前
import i18n from 'XXX/i18n-utils'
(async () => {
// 国际化文案异步初始化逻辑
await i18n.init({/* ... */})
root.render(<AppContainer />)
})()
// 开启 top level await 之后
import i18n from 'XXX/i18n-utils'
await i18n.init({/* ... */})
root.render(<AppContainer />)
Нам больше не нужно оборачивать асинхронный IIFE для нашей асинхронной логики, поверх логики JS мы можем напрямую использоватьawait
для управления асинхронной логикой.
Конечно, мы также можем использовать эту функцию для асинхронного экспорта или импорта модулей:
// src/Home/index.jsx
import React from 'react';
const Test = () => {
return <div>123</div>;
};
let Home = null;
await new Promise(resolve => {
Home = Test;
resolve();
});
export default Home;
// src/index.jsx
import Home from './Home'
Для поддержки обнаружения синтаксиса eslint нам также нужно добавить плагин babel@babel/plugin-syntax-top-level-await
чтобы наш Babel знал о синтаксисе ожидания верхнего уровня.
Однако, в отличие от того, как мы работаем с другими грамматиками ES6, мы не можем завершить процесс компиляции грамматики ожидания верхнего уровня в Babel, как описано на скриншоте домашней страницы плагина ниже, роль этого плагина состоит только в том, чтобы позволить Babel parse this Новый синтаксис преобразуется в AST, но не будет компилироваться, поэтому реальный процесс компиляции все равно должен выполняться с помощью инструмента сборки, такого как Webpack или Rollup.
окончательный эффект
Чтобы показать преимущества Webpack5 для проекта в процессе упаковки и сборки, мы провели следующие сравнения:
Сравнение эффективности сборки
Независимо от того, включен ли кеш файловой системы или нет, мы провели следующие сравнительные эксперименты для шаблонов проектов отдела. Можно видеть, что, помимо относительно длительного времени, затрачиваемого на начальное строительство, скорость последующего вторичного строительства значительно улучшилась.
- Первичная и вторичная сборки без настройки:
- Первичная и вторичная сборки с настроенным кешем:
настроить |
первая сборка |
Вторичная сборка |
Сборка после изменения кода |
Сборка после изменения конфигурации |
no-filesystem |
13.443s |
9.782s |
9.857s |
9.964s |
filesystem |
18.08s |
1.181s |
2.4s |
1.77s |
Сравнение частоты сбоев кеша продуктов обновления фрагментов
В качестве примера возьмем упакованные ресурсы фрагментов 8 js, указанные в приведенной выше функции долгосрочного кэширования.
Webpack4: новый фрагмент, сгенерированный в первую очередь, сделает недействительным кеш всех файлов js.
Webpack5: недействителен только для измененных файлов
Версия веб-пакета |
частота промахов кеша |
Webpack4 |
8/8=100% |
Webpack5 |
3/8=37.5% |
Конечно, окончательные преимущества, которые дало проекту обновление Webpack 5, намного больше, чем упомянутые выше.Нам также необходимо собрать больше данных, чтобы проверить более глубокие преимущества производительности, которые дает обновление Webpack 5 до стадии выполнения, но а пока В целом, многие возможности Webpack5 уже позволяют нам чувствовать себя намного комфортнее на этапе разработки.
Суммировать
Хотя Webpack5 предоставляет нам много отличных новых функций, восприятие изменений разработчиков в фактическом процессе разработки все еще относительно слабое Мы можем удобно использовать эти новые функции и в процессе обновления с помощью системы Webpack. экология, мы можем быстро найти четкое решение, когда сталкиваемся с проблемами, поэтому давайте испытать это вместе.
Если есть студенты, которые также заинтересованы в связанных возможностях Webpack5, мы также можем общаться и обсуждать в любое время~
Рекрутинг жесткий
Наша команда набирает сотрудников! ! ! Добро пожаловать в команду внешнего интерфейса ByteDance по монетизации бизнеса.Техническое строительство, которое мы делаем, включает в себя: обновление системы внешнего интерфейса, построение инфраструктуры командного узла, инструменты для публикации CI одним щелчком мыши, поддержку обслуживания компонентов, интернационализированный интерфейс. Общие решения, сверхмощные Опираясь на трансформацию микроинтерфейса бизнес-системы, систему визуального построения страниц, систему бизнес-аналитики BI, автоматическое тестирование интерфейса и т. д., команда разработчиков интерфейса Пекина, Шанхая и Ханчжоу 100 человек определенно найдут для вас области, представляющие интерес. Если вы хотите присоединиться к нам, добро пожаловать, нажмите на наш внутренний push-канал:
✨✨✨✨✨
Пуш-портал (золотой сезон вербовки, щелкните, чтобы получить внутреннюю возможность продвижения ByteDance! )
Эксклюзивный вход для набора в школу - код набора в школу ByteDance: HTZYCHN, ссылка для доставки:Присоединяйтесь к ByteDance-Рекрутмент
✨✨✨✨✨
Если вы хотите узнать о повседневной жизни (ду), жизни (би) и рабочей среде (ли) нашего отдела, вы также можетекликните сюдаЯ понимаю~
Добро пожаловать в "Byte Front End ByteFE"
Контактный адрес электронной почты для доставки резюме "tech@bytedance.com"