Пишите впереди:
В проекте разработки в онлайн-среду необходимо добавить несколько файлов js для статистики и печати журналов. Но для сред разработки очень важно ускорить упаковку и сократить время рендеринга страницы. Итак, я хочу написать простой загрузчик в соответствии со средой разработки, чтобы загружать некоторые ресурсы по требованию.
Например: в index.js добавьте ресурсы с пользовательской функцией envLoader.
index.js
//......
envLoader(
'/vendor/log.js'
)
//......
Для завершения функции погрузки по требованию. Мы планируем использовать пользовательский погрузчик. Реализация идей выглядит следующим образом:
- Добавьте загрузчик js для обработки index.js
- Разобрать функцию envLoader
- Получите входящие параметры и решите, следует ли загружать их в соответствии со средой.
Объедините API загрузчика с официального сайта, чтобы понять принцип работы загрузчика webpack.
будет использовать следующий API
- loader-utils
- schema-utils
- this.async
- this.cacheable
- getOptions
- validateOptions
- urlToRequest
Начните катиться своим собственным погрузчиком (^ - ^) v
Webpack Loader
Загрузчик используется для преобразования исходного кода модуля. Загрузчики позволяют предварительно обрабатывать файлы при импорте или «загрузке» модулей. Таким образом, загрузчики похожи на «задачи» в других инструментах сборки и предоставляют мощный способ обработки этапов сборки внешнего интерфейса. Загрузчики могут преобразовывать файлы с разных языков (например, TypeScript) в JavaScript или преобразовывать встроенные изображения в URL-адреса данных.
1. Основное использование
Загрузчик — это модуль узла, экспортируемый как функция. Эта функция вызывается, когда загрузчик конвертирует ресурсы. Данная функция будет вызывать API-интерфейс загрузчика и будет доступна через этот контекст.
Загрузчик является модулем узла, тогда его базовая форма выглядит следующим образом.
module.exports = function(source) {
return source;
};
- Загрузчик может передать только строку, содержащую содержимое файла ресурсов (источника).
- Если это синхронный загрузчик, вы можете использовать
return
илиthis.callback(err, value…)
Код возвращен - Асинхронный загрузчик: в асинхронном модуле метод обратного вызова, предоставляемый API-интерфейсом загрузчика, необходимо вызывать при возврате.
this.async
чтобы получить функцию обратного вызова:
module.exports = function(content, map, meta) {
var callback = this.async();
someAsyncOperation(content, function(err, result) {
if (err) return callback(err);
callback(null, result, map, meta);
});
};
2. Внедрение загрузчика в вебпак
На официальном сайте описано, как выделить одиночные и множественные загрузчики.
Главный принципpath.resolve
способ добавить путь к загрузчику. также можно использоватьresolveLoader.modules
Унифицированная конфигурация путей нескольких загрузчиков.
Webpack будет искать загрузчики в этих каталогах.Я создал новый локальный каталог загрузчиков в проекте и изменил файлы следующим образом:
webpack.config.js
module.exports = {
//...
resolveLoader: {// 配置查找loader的目录
modules: [
'node_modules',
path.resolve(__dirname, 'src', 'loaders')
]
},
module: {
rules:[
{
test: /\.js$/,
use: [
{
loader: 'env-loader',
options: {
env: process.env.NODE_ENV
}
},
{
loader:'babel-loader',
options: {
presets: ['env','es2015','react'],
}
},
]
}]
},
//...
};
Примечание: Режим выполнения загрузчика справа налево, цепное выполнение, результат обработки предыдущего загрузчика обрабатывает следующий.
Команды, упакованные в соответствии со средой, определены в package.json.
"scripts": {
"webpack": "cross-env NODE_ENV=development webpack-dev-server --open --mode development",
"test": "cross-env NODE_ENV=test webpack --mode development",
"dev": "cross-env NODE_ENV=dev webpack --mode development",
"prd": "cross-env NODE_ENV=prd webpack --mode development",
"boot":"cross-env NODE_ENV=boot webpack --mode development"
},
установивNODE_ENV
Чтобы различать среды dev и prd.
Q1: Как получить параметры среды, установленные в команде
A1:process.env
NODE_ENV, определенный во время упаковки, может быть получен для объекта.Когда env-loader введен в webpack.config.js, параметры могут быть переданы загрузчикуoptions
опции.
webpack.config.js
{
loader: 'env-loader',
options: {
env: process.env.NODE_ENV
}
},
3. Используйте библиотеку инструментов загрузчика для разбора параметров загрузчика.
- Пакет загрузчика-утилиты. Он предоставляет множество полезных инструментов, но одним из наиболее часто используемых является передача опций загрузчику.
- Пакет schema-utils работает с loader-utils, чтобы гарантировать соответствие параметров загрузчика структуре схемы JSON.
Использование пакета loader-utils в загрузчикеgetOptions
метод, получите параметр option загрузчика ({env:'dev'}. Используйте пакет schema-utils с loader-utils, чтобы обеспечить параметр загрузчика,进行与 JSON Schema结构一致的校验
. Добавление этих двух пакетов в index.js в:
env-loader/index.js
const loaderUtils = require('loader-utils')
const validate = require('schema-utils');
let json = {
"type": "object",
"properties": {
"content": {
"type": "string"
}
}
}
module.exports = function(source) {
this.cacheable();
let callback = this.async();
let options = loaderUtils.getOptions(this) //{env:'dev'}
validate(json, options, "env-loader");
}
В-четвертых, используйте esprima для разбора узлов js.
Парсер Esprima преобразует js-программы в синтаксическое дерево (AST), описывающее синтаксическую структуру программы. Результирующее синтаксическое дерево полезно для различных целей, от преобразования программы до статического анализа программы.
Я написал статью о AST раньшеЩелкните ссылку для просмотра, который здесь подробно описываться не будет.
Инструкции:
esprima.parseScript(input, config, delegate)
esprima.parseModule(input, config, delegate)
- input — это строка, представляющая программу для анализа
- config — это объект, используемый для настройки поведения синтаксического анализа (необязательно)
- делегат — это функция обратного вызова, вызываемая для каждого узла (необязательно)
С источником в качестве входного параметра программа будет преобразована в AST.
node возвращает синтаксис, соответствующий каждому узлу, а meta — это конкретное расположение узла в программе.
esprima.parseModule(source, {}, async(node, meta)=> {
console.log(node.meta)
//....
})
Результаты анализа следующие:
Проанализируйте, соответствует ли синтаксис каждого узла условиям оценки.Здесь оцените тип узла и имя==='envLoader' и тип==='Идентификатор' вызываемой функции и обработайте узлы, которые соответствуют условия.
function judgeType(node) {
return (node.type === 'CallExpression')
&& (node.callee.name === 'envLoader')
&& (node.callee.type === 'Identifier')
}
if (judgeType(node)) {
flag = true
node.arguments.map(argument=>{
entries.push({
val: argument.value,
start: meta.start.offset,
end: meta.end.offset
});
})
}
Пять, обработка пути к файлу
При анализе узла получается адрес внешнего ресурса, переданный в кастомной функции envLoader, после чего его нужно добавить в загрузчик.
Обычно используется в загрузчикеrequire()
илиimport
метод. Это потому, что веб-пакет находится в将模块路径转换为模块id
Хэш вычисляется раньше, поэтому мы должны избегать абсолютных путей, чтобы обеспечить согласованное хеширование между компиляциями.
Не вставляйте абсолютные пути в код модуля, потому что при изменении корневого пути проекта меняется и абсолютный путь к файлу.
loaderUtils.urlToRequest может преобразовывать URL-адреса некоторых ресурсов в запросы модуля веб-пакета.
//获取当前路径下的src文件夹
let downloadPath = path.resolve(process.cwd(), 'src')
if(env == 'prd'){
//如果是prd环境
//使用loaderUtils将请求转换为module
const saveUrl = loaderUtils.urlToRequest(`${extName}`,downloadPath);// "path/to/module.js"
//将转换好的module引入
var replaceText = `import "${saveUrl}"`
}else{
//其他环境
var replaceText = 'function envLoad(){}'
}
//将envLoader函数替换
source = source.replace(transText, replaceText);
6. Тест
После выполнения вышеуказанных шагов был разработан простой загрузчик, который можно запускать локально. Далее давайте воспользуемся простым модульным тестом, чтобы убедиться, что загрузчик ведет себя так, как мы ожидаем.
Мы будем использовать фреймворк Jest. Затем нам также нужно установить babel-jest и некоторые пресеты, позволяющие использовать import/export и async/await.
6.1 Установка зависимостей
npm install --save-dev jest babel-jest babel-preset-env
.babelrc
{
"presets": [[
"env",
{
"targets": {
"node": "4"
}
}
]]
}
Наш загрузчик будет обрабатывать файлы .js и будет
envLoader('xxx')
Заменено в среде разработки наfunction envLoad(){}
и замените его на import «path/xxx.js» в производственной среде.
Создайте новый example.js в тестовой папке.
envLoader(
'/vendor/lodash.min.js'
)
Мы будем использовать Node.js API и memory-fs для выполнения webpack.
npm install --save-dev webpack memory-fss
test/compiler.js
import path from 'path';
import webpack from 'webpack';
import memoryfs from 'memory-fs';
export default (fixture, options = {}) => {
const compiler = webpack({
context: __dirname,
entry: `./${fixture}`,
output: {
path: path.resolve(__dirname),
filename: 'bundle.js',
},
module: {
rules: [{
test: /\.js$/,
use: {
loader: path.resolve(__dirname, '../src/loaders/env-loader'),
options: {
env: process.env.NODE_ENV
}
}
}]
}
});
compiler.outputFileSystem = new memoryfs();
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
if (err || stats.hasErrors()) reject(err);
resolve(stats);
});
});
};
Наконец, давайте напишем тест и добавим скрипт npm для его запуска.
import compiler from './compiler.js';
test('envLoader to import', async () => {
const stats = await compiler('example.js');
const output = stats.toJson().modules[0].source;
if(process.env.NODE_ENV == 'prd'){
expect(output).toBe('import "/Users/yuan/Documents/yuanyuan/Project/env-loader/src/vendor/lodash.min.js"');
}else{
expect(output).toBe('function envLoad(){}');
}
});
package.json
{
"scripts": {
"test-boot": "cross-env NODE_ENV=boot jest",
"test-prd": "cross-env NODE_ENV=prd jest"
}
}
Запуск двух скриптов по отдельности
Каждая проверка прошла успешно ~ тест пройден
адрес env-загрузчикаПодробный процесс внедрения нажмите здесь! !
Объявление о вакансии
ByteDance набирает сотрудников!
Описание вакансии: Front-end development (senior) ToB направление - видео облако (База: Шанхай, Пекин)
1. Отвечает за производство мультимедийных услуг, таких как аудио и видео по запросу / прямая трансляция / общение в реальном времени и создание облачных платформ для бизнеса;
2. Отвечает за мультимедийную систему качества, эксплуатацию и техническое обслуживание, построение и развитие системы;
3. Хорошо разбирается в абстрактном дизайне, инженерном мышлении, фокусируется на взаимодействии и создает максимальный пользовательский опыт.
Профессиональные требования
1. Компьютеры, связь и электронная информатика и другие смежные специальности являются предпочтительными;
2. Владение различными фронтенд-технологиями, включая HTML/CSS/JavaScript/Node.js и т. д.;
3. Глубокое понимание языка JavaScript с использованием основных сред разработки, таких как React или Vue.js;
4. Приветствуется знание Node.js, понимание Express/KOA и других фреймворков, а также опыт разработки крупномасштабных серверных программ;
5. Иметь определенное представление о пользовательском опыте, интерактивной работе и анализе потребностей пользователей, а также иметь опыт разработки продуктов или интерфейсов;
6. Предпочтение отдается участникам со своими собственными техническими продуктами, работами с открытым исходным кодом или активным сообществом с открытым исходным кодом.
Основные моменты работы
Команда видеооблачных сервисов опирается на накопленные аудио- и видеотехнологии и базовые ресурсы Douyin, Xigua Video и других продуктов, чтобы предоставлять клиентам универсальные аудио- и видеомультимедийные услуги, включая аудио- и видеопо запросу, прямую трансляцию, реальную связь времени, обработка изображений и т. д. Внутренне, как центр видеотехнологий, он обслуживает внутренний бизнес; снаружи он создает готовые аудио- и видео-мультимедийные сервисные решения для обслуживания пользователей корпоративного уровня.
У команды есть стандартизированный процесс итерации проекта и идеальная конфигурация ролей проекта; сильная техническая атмосфера, охватывает сообщество открытого исходного кода и регулярно делится, так что каждый может быстро расти вместе с бизнесом и использовать технологии, чтобы изменить мир!
способ доставки
Резюме можно отправлять напрямую по адресу:yuanyuan.wallace@bytedance.com
Вы также можете отсканировать внутренний QR-код для доставки онлайн, с нетерпением жду вашего присоединения! ~