Frontender Magazine
Есть несколько модных инструментов для автоматизации сборки в javascript-проектах, которые я никогда не находил привлекательными, потому как знаком с менее известной командой npm run , которой вполне достаточно для всего, что мне необходимо делать, сохраняя при этом достаточно маленький конфигурационный файл.
Вот несколько трюков, которые я использую чтобы получить максимальную отдачу от npm run и полей script в package.json .
Поле «script»
Возможно вы этого не знали, но npm содержит поле под названием scripts в файле package.json проекта для того, чтобы делать такие команды, как npm test , фактически, выполняющая содержимое поля scripts.test , и npm start , вызывающая инструкции из поля scripts.start .
npm test и npm start — это, всего лишь, удобные ссылки для npm run test и npm run start . С помощью npm run можно выполнить совершенно любое содержимое любого поля внутри scripts .
Кроме того, npm run великолепен ещё и потому, что npm автоматически добавляет в $PATH директорию node_modules/.bin , так что вы можете напрямую запускать команды из dependencies или devDependencies , без необходимости устанавливать это модули глобально. npm-пакеты, которые вы хотели бы включить в свой воркфлоу, должны иметь всего лишь простой интерфейс командной строки, и вы сможете написать простую автоматизацию самостоятельно.
Сборка javascript
Я пишу клиентский код, используя для его организации принятые в commonjs module.exports и require() и подключая модули, опубликованные в npm. browserify может преобразовать все вызовы require() в статический код, на этапе сборки, создав единый склееный бандл-файл, который можно загрузить, используя тег script . Для использования browserify я просто держу в package.json поле scripts[‘build-js’] , которое выглядит так:
"build-js": "browserify browser/main.js > static/bundle.js"
Если я хочу собрать javascript для продакшна, я также выполняю минификацию — подключаю uglify-js как devDependency и дописываю его через пайп:
"build-js": "browserify browser/main.js | uglifyjs -mc > static/bundle.js"
Отслеживание изменений в javascript
Для автоматической перекомпиляции клиентского javascript при любых изменениях файлов, я просто заменяю команду browserify на watchify и добавляю ключи -d и -v для дебага и более подробного вывода.
"watch-js": "watchify browser/main.js -o static/bundle.js -dv"
Сборка CSS
Я обнаружил, что cat обычно полностью удовлетворяет мои потребности, так что я просто держу для сборки что-то вроде этого:
"build-css": "cat static/pages/*.css tabs/*/*.css > static/bundle.css"
Отслеживание изменений в css
Так же как и с watchify , я пересобираю css при изменениях с помощью замены cat на catw:
"watch-css": "catw static/pages/*.css tabs/*/*.css -o static/bundle.css -v"
Последовательности задач
Если у вас есть две задачи, которые вы хотели бы запускать последовательно, то вы можете записать их через npm run и разделив их с помощью && :
"build": "npm run build-js && npm run build-css"
Параллельные задачи
Если вам нужно запустить несколько задач параллельно, просто разделите их с помощью & :
"watch": "npm run watch-js & npm run watch-css"
Получившийся package.json
Соединив всё, о чем я говорил, мы получим примерно такой package.json
< "name": "my-silly-app", "version": "1.2.3", "private": true, "dependencies": < "browserify": "~2.35.2", "uglifyjs": "~2.3.6" >, "devDependencies": < "watchify": "~0.1.0", "catw": "~0.0.1", "tap": "~0.4.4" >, "scripts": < "build-js": "browserify browser/main.js | uglifyjs -mc > static/bundle.js", "build-css": "cat static/pages/*.css tabs/*/*.css", "build": "npm run build-js && npm run build-css", "watch-js": "watchify browser/main.js -o static/bundle.js -dv", "watch-css": "catw static/pages/*.css tabs/*/*.css -o static/bundle.css -v", "watch": "npm run watch-js & npm run watch-css", "start": "node server.js", "test": "tap test/*.js" > >
Если мне нужно выполнить сборку для продакшна, я просто выполняю npm run build . Для локальной разработки я запущу npm run watch .
Вы можете расширять базовое приближение как хотите! Например, вам может понадобиться выполнить build до запуска start , в этом случае вы просто напишете:
"start": "npm run build && node server.js"
Или, возможно, вы захотите создать команду npm run start-dev , которая также запустит вотчеры:
"start-dev": "npm run watch & npm start"
Вы можете реорганизовать все части так, как хотите!
Когда становится действительно сложно…
Если вы поняли, что вбили слишком много команд в одно поле scripts , то советую вам подумать над тем, чтобы вынести некоторые из этих команд в отдельное место, такое как bin/ .
Эти скрипты можно написать на bash, на node, на perl, да на чем угодно! Просто добавьте свойство #! в начало файла, выполните chmod +x , получится так:
#!/bin/bash (cd site/main; browserify browser/main.js | uglifyjs -mc > static/bundle.js) (cd site/xyz; browserify browser.js > static/bundle.js) "build-js": "bin/build.sh"
Если вам совершенно точно нужно собирать ваш проект на windows, просто удостоверьтесь, что у разработчиков, которые пользуются windows, есть копия msysgit, которая поставляется вместе с bash, cygwin или чем-то похожим. Или предложите им перейти на UNIX.
Я много экспериментировал, решая проблему невозможности запуска некоторых команд bash в терминале windows, но работа пока далека от завершения.
Вывод
Я надеюсь, что те примеры использования npm run , которые я описал здесь, помогут тем из вас, кто не был вдохновлен текущим состоянием дел в инструментах для сборки фронтенда, и особенно тем, кто, как и я, не проникся призывами этих инструментов. Я предпочитаю инструменты, пропитанные наследием UNIX, такие, как git, или npm, о котором я говорил здесь. Эти инструменты предоставляют быстрый и минималистичный интерфейс, с которым можно взаимодействовать через bash. Некоторые из этих штук не требуют долгих церемоний, или обсуждений. Можно зайти очень далеко, используя очень простые инструменты, которые делают очень обычные вещи.
Если вам не нравится стиль npm run , о котором я рассказал здесь, вы можете присмотреться к Мakefile, как к простой и проверенной временем альтернативе.
What Are «npm run dev» and «npm run prod»
Are these native npm commands or custom Laravel Mix commands? Where are they defined? I noticed they are listed as «scripts» in the Laravel package.json. What exactly are these scripts, custom commands for Webpack via Laravel Mix?
"scripts": < "dev": "npm run development", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "npm run development -- --watch", "watch-poll": "npm run watch -- --watch-poll", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" >,
asked Oct 16, 2020 at 22:08
3,674 12 12 gold badges 54 54 silver badges 97 97 bronze badges
You seem to have found what they are and where they’re defined, so what’s your question exactly? They’re NPM scripts.
Oct 16, 2020 at 22:21
What do they run, cross-env or webpack.js? Thanks for your help.
Oct 16, 2020 at 22:38
2 Answers 2
They are indeed the scripts as defined in the package.json file as you discovered. The values are run by your shell (so, for example, bash , zsh , etc. on UNIX-like operating systems).
One key thing to note is that the node_modules/.bin directory is added to PATH before executing. So, in the case of the two scripts you’re asking about, cross-env can be found in node_modules/.bin (because it’s almost certainly specified as a devDependency elsewhere in the package.json ) as long as you’ve already run npm install or npm ci within the project directory.
answered Oct 16, 2020 at 22:45
66.9k 24 24 gold badges 175 175 silver badges 212 212 bronze badges
Yeah, cross-env is listed in devDependencies. Thanks for your help, it helped me understand how these two custom scripts function, which is what I was looking for!
Oct 16, 2020 at 22:50
Those commands are used at any project which supports JSON files on NPM. Regarding OP questions:
Are these native npm commands or custom Laravel Mix commands? Where are they defined?
- npm : One could say that it is a command native to the system, for calling Node Package Manager program. In Windows, for example, it should be the default command for calling npm from any console.
- run : It is a command native to npm. More information here. Keep in mind this is an aliases to the original command run-script .
- dev and prod : They’re user defined.
- dev : Used for running the specific commands for serving the project, to any server, to live development. In the case of a web page, you’ll see your web page in the browser, and any change you make to the HTML code, for example, will be reflected immediately in the page you see in your browser.
- prod : Compiles all the necessary files for production. Final product. In the case of a web page, for example, the HTML, CSS, and JS files you’ll handle to the client. The result of running this command, it is expected to be one single folder with all the afore mentioned content.
I noticed they are listed as «scripts» in the Laravel package.json. What exactly are these scripts, custom commands for Webpack via Laravel Mix?
- «dev»: «npm run development» : Runs the commandment immediately below, which is: «development»: «cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js —progress —hide-modules —config=node_modules/laravel-mix/setup/webpack.config.js» . What this line of code does, depends on what dependencies you have on your project (see the node_modules folder, and read their respective documentation).
- «prod»: «npm run production» : It has the same description than the item above, but for npm run prod
Сборка фронтенда (Laravel Mix)
Laravel Mix — это чистый и гибкий API для определения инструкций сборки Webpack для вашего Laravel-приложения с использованием нескольких основных препроцессоров CSS и JavaScript. С помощью сцепки методов вы можете гибко определить свой конвейер сборки. Например:
mix.js('resources/assets/js/app.js', 'public/js') .sass('resources/assets/sass/app.scss', 'public/css');
Если вы не знали, с какой стороны подойти к Webpack и вообще к сборке фронтенда, то вам точно понравится Laravel Mix. Но вам необязательно использовать именно его при разработке своего приложения. Вы можете использовать любой другой инструмент для сборки, или вообще не использовать его.
Установка и настройка
Установка Node
Перед запуском Mix необходимо убедиться, что на вашей машине установлены Node.js и NPM.
node -v npm -v
По умолчанию Laravel Homestead включает в себя всё необходимое. Однако, если вы не используете Vagrant, то вы можете легко установить последнюю версию Node и NPM, используя простые графические установщики с их страницы загрузки.
Laravel Mix
Послений оставшийся шаг — установить Laravel Mix. В свежей установке Laravel вы найдете файл package.json в корне вашей структуры директорий. Файл package.json по умолчанию включает все необходимое, чтобы начать. Подумайте об этом как о вашем файле composer.json , кроме того, что он определяет Node-зависимости вместо PHP. Вы можете установить зависимости, запустив:
npm install
Если вы занимаетесь разработкой на системе Windows или ваша VM работает на Windows-хосте, вам может потребоваться выполнить команду npm install с ключом —no-bin-links :
npm install --no-bin-links
Запуск Mix
Mix — это слой настройки поверх Webpack, поэтому для запуска задач Mix вам нужно только выполнить один из NPM-скриптов, который включен в файл Laravel package.json по умолчанию:
// Запустить все задачи Mix. npm run dev // Запустить все задачи Mix и минифицировать вывод. npm run production
Отслеживание изменений ассетов
Команда npm run watch продолжит выполняться в терминале и будет следить за всеми изменениями ваших ресурсов. Когда что-либо изменится, автоматически скомпилируются новые файлы:
npm run watch
Вы можете обнаружить, что в определенных средах Webpack не обновляется, когда меняются ваши файлы. Если это как раз то, с чем вы столкнулись, попробуйте использовать команлу watch-poll :
npm run watch-poll
Работа с таблицами стилей
Файл webpack.mix.js — ваша точка входа для компиляции всех ассетов. Считайте его легкой оболочкой для настройки поверх Webpack. Задачи Mix можно связать вместе, чтобы конкретно указать как должны компилироваться ваши ассеты.
Less
Метод less можно использовать для компилирования Less в CSS. Давайте скомпилируем наш первичный файл app.less в public/css/app.css .
mix.less('resources/assets/less/app.less', 'public/css');
Множественные вызовы метода less можно использовать для компилирования нескольких файлов:
mix.less('resources/assets/less/app.less', 'public/css') .less('resources/assets/less/admin.less', 'public/css');
Если вы хотите изменить имя файла скомпилированного CSS, вы можете передать полный путь в качестве второго аргумента методу less :
mix.less('resources/assets/less/app.less', 'public/stylesheets/styles.css');
Если нужно переопределить лежащие в основе plug-in опции Less, то можно передать объект в качестве третьего аргумента mix.less() :
mix.less('resources/assets/less/app.less', 'public/css', < strictMath: true >);
Sass
Метод sass позволяет компилировать Sass в CSS. Вы можете использовать метод следующим образом:
mix.sass('resources/assets/sass/app.scss', 'public/css');
Как и в случае с методом less , вы можете компилировать несколько файлов Sass в их соответствующие CSS-файлы и даже настроить директорию вывода итогового CSS:
mix.sass('resources/assets/sass/app.sass', 'public/css') .sass('resources/assets/sass/admin.sass', 'public/css/admin');
Дополнительные plug-in опции Node-Sass можно указать в качестве третьего аргумента:
mix.sass('resources/assets/sass/app.sass', 'public/css', < precision: 5 >);
Stylus
Схоже с Less и Sass, метод stylus позволяет компилировать Stylus в CSS:
mix.stylus('resources/assets/stylus/app.styl', 'public/css');
Вы также можете установить дополнительные плагины Stylus, такие как Rupture. Сначала установите требуемый плагин через NPM ( npm install rupture ) и затем затребуйте его в своем вызове mix.stylus() :
mix.stylus('resources/assets/stylus/app.styl', 'public/css', < use: [ require('rupture')() ] >);
PostCSS
PostCSS — мощный инструмент для трансформации CSS, который включен в Laravel Mix. По умолчанию Mix пользуется популярнм плагином Autoprefixer для автоматического применения всех необходимых вендор-префиксов CSS3. Вы свободно можете добавлять любые дополнительные плагины, которые подходят для вашего приложения. Сначала нужно установить желаемые плагины через NPM и затем обратиться к ним в вашем файле webpack.mix.js :
mix.sass('resources/assets/sass/app.scss', 'public/css') .options(< postCss: [ require('postcss-css-variables')() ] >);
Простой CSS
Если вам просто хотелось бы сконцентрировать некоторые простые таблицы стилей CSS в единый файл, то можно воспользоваться методом styles .
mix.styles([ 'public/css/vendor/normalize.css', 'public/css/vendor/videojs.css' ], 'public/css/all.css');
Обработка URL
Так как Laravel Mix строится поверх Webpack, крайне важно понять некоторые концепты Webpack. Для компиляции CSS Webpack будет перезаписывать и оптимизировать любой вызов url() в рамках ваших таблицей стилей. Хотя это и может звучать странно, это невероятно мощный функционал. Представьте, что мы хотим скомпилировать Sass, который включает относительный URL, в изображение:
.example < background: url('../images/example.png'); >
Абсолютные пути для любого заданного url() будут исключены из перезаписывания URL. Например, url(‘/images/thing.png’) или url(‘http://example.com/images/thing.png’) не будут изменены.
По умолчанию Laravel Mix и Webpack найдут example.png , скопируют их в вашу папку public/images , а затем перезапишут url() в вашей сгенерированной таблице стилей. Таким образом, ваш скомпилированный CSS будет:
.example < background: url(/images/example.png?d41d8cd98f00b204e9800998ecf8427e); >
Хотя эта функция и полезна, возможно ваша существующая папка уже настроена так, как вам нравится. Если это именно ваш случай, можно отключить перезаписывание url() :
mix.sass('resources/assets/app/app.scss', 'public/css') .options(< processCssUrls: false >);
После добавления вышеуказанного в ваш файл webpack.mix.js , Mix больше не будет сопоставлять любой url() или копировать ассеты в вашу общую директорию. Другими словами, скомпилированный CSS будет выглядеть так же, как вы его и напечатали изначально:
.example < background: url("../images/thing.png"); >
Source Maps (файлы с информацией, которая требуется при отладке)
Хотя они и отключены по умолчанию, source maps (файлы с информацией, которая требуется при отладке) можно активировать, вызвав метод mix.sourceMaps() в вашем файле webpack.mix.js . Хотя это и связано с ценой компиляции/производительности, это обеспечит дополнительную отладочную информацию инструментам разработчика вашего браузера при использовании скомпилированных ассетов.
mix.js('resources/assets/js/app.js', 'public/js') .sourceMaps();
Работа с JavaScript
Mix предоставляет несколько функций для работы с JavaScript-файлами, например: компилирование ECMAScript 2015, бандлинг модулей, минификация и простая конкатенация простых JavaScript-файлов. Даже лучше: это все работает незаметно для пользователя, не требуя ни грамма пользовательской настройки:
mix.js('resources/assets/js/app.js', 'public/js');
Используя эту единственную строку кода теперь вы можете воспользоваться следующими плюсами:
— Синтаксис ES2015. — Модули — Компиляция файлов `.vue`. — Минификация для продакшна.
Извлечение библиотек поставщика
Одним из потенциальных недостатков бандлинга всего JavaScript приложения с вашими библиотеками поставщиков является то, что это затрудняет долгосрочное кэширование. Например, одно обновление вашего кода приложения заставит браузер повторно загружать все ваши библиотеки поставщиков, даже если они не изменились.
Если вы планируете часто обновлять JavaScript своего приложения, то вам следует рассмотреть вариант извлечение всех своих внешних библиотек в отдельный файл. Таким образом, изменение кода вашего приложения не повлияет на кеширование вашего большого файла vendor.js . Метод extract в Mix делает эту задачу чрезвычайно простой:
mix.js('resources/assets/js/app.js', 'public/js') .extract(['vue'])
Метод extract принимает массив всех библиотек или модулей, которые вы бы хотели извлечь в файл vendor.js . Используя вышеуказанный сниппет в качестве примера, Mix сгенерирует следующие файлы:
— `public/js/manifest.js`: *Webpack manifest runtime* — `public/js/vendor.js`: *Ваши библиотеки поставщика* — `public/js/app.js`: *Код вашего приложения*
Убедитесь, что загрузили эти файлы в соответствующем порядке, чтобы избежать ошибок JavaScript:
script src="/js/manifest.js"> script> script src="/js/vendor.js"> script> script src="/js/app.js"> script>
React
Mix может автоматически установить Babel-плагины, необходимые для поддержки React. Для начала замените mix.js() на mix.react() :
mix.react('resources/assets/js/app.jsx', 'public/js');
Mix в фоновом режиме скачает и включит подходящие Babel-плагины babel-preset-react .
Vanilla JS
Схоже с комбинирование таблиц стилей с mix.styles() , вы также можете скомбинировать и минифицировать любое количество файлов JavaScript при помощи метода scripts() :
mix.scripts([ 'public/js/admin.js', 'public/js/dashboard.js' ], 'public/js/all.js');
Эта опция особенно полезна для прежних версий проектов, где вам не требовалась компиляция Webpack для вашего JavaScript.
Вариация mix.scripts() — mix.babel() . Сигнатура этого метода идентична scripts ; однако, конкатенированный файл получит компиляцию Babel, которая переводит любой код ES2015 в vanilla JavaScript, который поймут все браузеры.
Пользовательская настройка Webpack
Laravel Mix обращается к преднастроенному файлу webpack.config.js . Время от времени вам может потребоваться вручную изменить этот файл. У вас, возможно, есть специальный лоадер или плагин, который нужно указывать, или может вы предпочитаете использовать Stylus вместо Sass. В таких случаях у вас будет два выбора:
Слияние пользовательской настройки
Mix предоставляет полезный метод webpackConfig , который позволит выполнить слияение любых коротких Webpack-переопределений. Это крайне привлекательный выбор, так как от вас не требуется копировать и поддерживать собственную копию файла webpack.config.js . Метод webpackConfig принимает объект, который должен содержать любую специальную настройку Webpack, которую вы желаете применить.
mix.webpackConfig(< resolve: < modules: [ path.resolve(__dirname, 'vendor/laravel/spark/resources/assets/js') ] > >);
Пользовательские файлы настроек
Скопируйте файл node_modules/laravel-mix/setup/webpack.config.js в корневую директорию вашего проекта, если вы бы хотели полностью изменить свою настройку Webpack. Затем укажите все ссылки —config в своем файле package.json на этот скопированный конфиг. Если вы решите воспользоваться этим подходом, любые будущие upstream-обновления webpack.config.js вашего Mix следует вручную склеивать с вашим измененным файлом.
Копирование файлов и директорий
Метод copy используется для копирования файлов и папок в новое место. Это может пригодиться, когда нужно переместить определенный ассет из директории node_modules в вашу папку public .
mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');
При копировании директории метод copy сделает структуру директории более плоской. Если нужно поддерживать оригинальную структуру директории, вместо этого следует использовать метод copyDirectory :
mix.copyDirectory('assets/img', 'public/img');
Версии файлов /очистка кэша
Многие разработчики добавляют в имена ресурсов время создания или уникальный токен, чтобы браузер загружал свежие ресурсы вместо обработки устаревшего кода. В Mix для этого служит метод version .
Метод version автоматически добавит уникальный хеш к именам всех скомпилированных файлов, что способствует более удобной очистке кэша:
mix.js('resources/assets/js/app.js', 'public/js') .version();
Сгенерировав версию файла, вы можете использовать глобальную функцию Laravel PHP mix в ваших шаблонах для загрузки соответствующих хешированных ресурсов. Функция mix автоматически определит имя хешированного файла:
link rel="stylesheet" href=">">
Так как во время разработки обычно нет необходимости в версионированных файлах, вы можете указать, чтобы процесс версионировання запускался только во время npm run production :
mix.js('resources/assets/js/app.js', 'public/js'); if (mix.inProduction())
Перезагрузка Browsersync
BrowserSync автоматически производит обновление в браузере при изменениях в ваших ресурсах. Вы можете использовать метод mix.browserSync() :
mix.browserSync('my-domain.dev'); // Or. // https://browsersync.io/docs/options mix.browserSync(< proxy: 'my-domain.dev' >);
Этому методу можно передавать либо строку (прокси), либо объект (настройки BrowserSync). Затем запустите дев-сервер Webpack, используя команду npm run watch . Теперь, когда вы изменяете скрипт или файл PHP, смотрите как браузер сразу же обновляет страницу, чтобы отразить внесенные изменения.
Переменные среды
Вы можете внедрите переменные среды в Mix, укахав префикс MIX_ ключу в вашем файле .env :
MIX_SENTRY_DSN_PUBLIC=http://example.com
После того как переменная была задана в вашем файле .env , вы можете получить доступ через объект process.env . Если значение меняет во время выполнения задачи watch , вам потребуется перезапустить задачу:
process.env.MIX_SENTRY_DSN_PUBLIC
Уведомления
Когда доступно, Mix будет автоматически отображать уведомления ОС для каждого бандла. Это даст вам мгновенную обратную связь о том, была ли компиляция успешной или нет. Однако, иногда может потребоваться отключить эти уведомления. Одним из таких примеров может быть запуск Mix на вашем продакшн-сервере. Уведомления можно отключить через метод disableNotifications .
mix.disableNotifications();
Русскоязычное комьюнити
- Группа в VK
- Телеграм LaravelRUS
- Телеграм Laravel для новичков
- Телеграм LaravelPro
Обучающие ресурсы
- Laracasts
- Codecourse
- Курс Дмитрия Елисеева
- Adam Wathan
Блоги разработчиков
- Laravel News
- Freek Van der Herten
- Brent Roose
- Marcel Pociot
13 приёмов работы с npm, которые помогают экономить время
Каждый день миллионы разработчиков, создавая свои JavaScript-приложения, обращаются к npm (или к Yarn). Выполнение команд наподобие npm init или npx create-react-app стало привычным способом начала работы над практически любым JavaScript-проектом. Это может быть сервер, клиент, или даже настольное приложение.
Но утилита npm способна не только на инициализацию проектов или на установку пакетов. Автор материала, перевод которого мы сегодня публикуем, хочет рассказать о 13 хитростях npm, которые позволят выжать из этой системы всё, что можно. Здесь будут рассмотрены приёмы разного масштаба — от использования сокращений команд до настройки поведения npm init .
Многие программисты пользуются npm ежедневно. Это значит, что в долгосрочной перспективе изменить что-то в лучшую сторону может даже небольшая экономия времени. Этот материал рассчитан, преимущественно, на начинающих разработчиков и на разработчиков среднего уровня. Однако даже если вы — профессионал, автор материала надеется, что вы сможете найти здесь пару интересных вещей, с которыми вы раньше не сталкивались.
Если вы совершенно не знакомы с npm — знайте, что интересующая нас программа устанавливается вместе с Node.js. Если вы работаете в Windows, то, чтобы воспроизвести кое-что из того, о чём здесь пойдёт речь, рекомендуется установить Git Bash.
1. Краткие варианты записи основных команд
Начнём с основ. Потратив немного времени на изучение сокращённых вариантов самых распространённых команд npm, вы сэкономите себе немало времени в будущем.
- Установка пакетов. Обычный вариант: npm install . Сокращённый вариант: npm i .
- Запуск тестов. Обычный вариант: npm test . Сокращённый вариант: npm t .
- Вызов справки. Обычный вариант: npm —help . Сокращённый вариант: npm -h .
- Флаг глобальной установки. Обычный вариант: —global . Сокращённый вариант: -g .
- Флаг установки пакета в качестве зависимости разработки. Обычный вариант: —save-dev . Сокращённый вариант: -D .
- Принятие установок npm init , применяемых по умолчанию. Обычный вариант: npm init —yes или npm init —force . Сокращённый вариант: npm init -y или npm init -f .
▍Краткие варианты записи менее распространённых команд
Вот ещё несколько полезных сокращений, которые, однако, используются не так широко как те, что мы только что рассмотрели.
- Сохранение пакета в виде опциональной зависимости. Обычный вариант: —save-optional . Сокращённый вариант: -O .
- Сохранение сведений о точной версии пакета. Обычный вариант: —save-exact . Сокращённый вариант: -E .
▍Сокращение для корневой директории
Обычно символ «точка» ( . ) используется для представления корневой директории приложения, или (в зависимости от контекста) — для представления точки входа в приложение. В npm это — то, что задано в качестве значения свойства main в файле package.json :
Это сокращение можно использовать, например, с командами наподобие npx create-react-app . Так, вместо того, чтобы запускать эту команду в виде npx create-react-app my-app (что приведёт к созданию новой папки my-app ), можно запустить эту команду так: npx create-react-app . (обратите внимание на точку, которая идёт после команды). Это позволит создать шаблонный проект React-приложения в той папке, в которой вы находитесь в момент запуска команды.
2. Установка значений по умолчанию для npm init
Постоянно запуская команду npm init для создания нового проекта, вы скорее всего обнаружите, что снова и снова вводите в ответ на вопросы системы одни и те же данные. Например — вполне вероятно то, что именно вы являетесь автором большинства создаваемых вами проектов. Для того чтобы сэкономить время на вводе одних и тех же данных, вы можете установить собственные значения по умолчанию для соответствующих полей:
npm config set init.author.name "Joe Bloggs" npm config set init.author.email "joebloggs@gmail.com" npm config set init.author.url "joebloggs.com" npm config set init.license "MIT"
Для того чтобы проверить правильность добавления подобных сведений в систему — введите команду npm config edit . Это приведёт к открытию конфигурационного файла в системном редакторе. Если вы хотите отредактировать глобальные параметры npm — воспользуйтесь командой npm config edit -g .
Для того чтобы вернуться к настройкам по умолчанию — можете воспользоваться следующим скриптом. Его первая строка удаляет из файла конфигурационные данные, а вторая заполняет его значениями по умолчанию.
echo "" > $(npm config get userconfig) npm config edit
Вышеприведённый скрипт сбрасывает значения по умолчанию для пользователя. Следующий скрипт сбрасывает к исходному состоянию глобальные значения по умолчанию:
echo "" > $(npm config get globalconfig) npm config --global edit
3. Кросс-платформенные скрипты
Любой код, выполняемый в командной строке, может столкнуться с проблемами совместимости. Особенно это касается несовместимости между системами, основанными на Windows и на Unix (сюда входят Mac и Linux). Это — не проблема, если над неким проектом работаете вы и только вы. Но во многих случаях кросс-платформенная совместимость скриптов весьма важна. Например, работа независимо от операционной системы — это огромный плюс для любого опенсорсного, учебного или демонстрационного проекта.
К счастью, решить проблему совместимости скриптов не особенно сложно. В нашем распоряжении есть несколько вариантов. Однако тут мне хотелось бы рассказать об одном из них, о том, используя который я получил наилучшие результаты. Речь идёт о пакете cross-env. Его нужно установить как зависимость разработки с использованием команды npm i -D cross-env . Затем нужно поставить cross-env перед каждой переменной окружения. Например — это может выглядеть так:
Я обнаружил, что пакет cross-env — это самый удобный инструмент для достижения кросс-платформенной совместимости скриптов. Но вам полезно будет взглянуть ещё и на следующие два популярных инструмента, которые могут помочь в решении этой задачи:
- Пакет rimraf. Его, для запуска кросс-платформенных скриптов, можно установить глобально.
- Пакет ShellJS. Это — переносимая Node.js-реализация командной оболочки Unix.
4. Параллельный запуск скриптов
Для того чтобы организовать последовательное выполнение команд в командной оболочке Linux используется конструкция && . А как насчёт параллельного запуска скриптов? Для достижения этой цели можно подобрать соответствующий npm-пакет. Самыми популярными пакетами такого рода являются concurrently и npm-run-all. Здесь мы продемонстрируем применение пакета concurrently.
Для начала выбранный пакет нужно установить в качестве зависимости разработки: npm i -D concurrently . Затем в package.json можно воспользоваться конструкцией следующего вида:
5. Запуск скриптов, находящихся в различных директориях
Иногда приходится сталкиваться с приложениями, в которых имеется несколько файлов package.json , расположенных в различных директориях. Удобно было бы, например, запускать объявленные в них скрипты, находясь в корневой директории проекта. Это — куда лучше, чем необходимость путешествовать по разным папкам всякий раз, когда нужно запустить некий скрипт. Для того чтобы это сделать можно воспользоваться следующими двумя подходами.
Для начала, можно воспользоваться командой cd для организации автоматического перехода в нужную директорию. Выглядеть это может примерно так:
cd folder && npm start && cd ..
Но эту задачу можно решить и более интересным способом. Он заключается в использовании флага —prefix , с помощью которого можно указать путь:
npm start --prefix path/to/your/folder
Ниже показан пример применения этого решения из реального приложения. Тут нам нужно выполнить npm start для клиентской и серверной частей проекта. Их код, соответственно, находится в папках client и server .
"start": "concurrently \"(npm start --prefix client)\" \"(npm start --prefix server)\"",
6. Откладывание запуска скрипта до тех пор, пока не будет доступен некий ресурс
При разработке фулстек-приложений часто возникает нужда в том, чтобы запускать и клиентскую, и серверную часть приложения. Пакет wait-on позволяет обеспечить синхронизацию выполнения неких процессов. В нашем случае нужно, чтобы перед запуском клиентской части приложения был бы доступным определённый порт.
Например, есть dev-скрипт, который используется в Electron-приложении, интерфейс которого написан с помощью React. Скрипт, используя concurrently , параллельно запускает презентационный слой приложения и окно Electron. Но с использованием wait-on можно сделать так, чтобы окно Electron открылось бы только тогда, когда презентационный слой React будет готов к работе и окажется доступен по адресу http://localhost:3000 . Вот как выглядит использование wait-on :
"dev": "concurrently \"cross-env BROWSER=none npm run start\" \"wait-on http://localhost:3000 && electron .\"",
Кроме того, стандартным поведением React-проектов является автоматическое открытие окна браузера. В случае использования React с Electron в этом нет необходимости. Отключить это можно с помощью переменной окружения BROWSER=none , перед которой, ради кросс-платформенной совместимости решения, находится команда cross-env .
7. Вывод списка доступных скриптов и работа с ними
Для того чтобы вывести список скриптов, доступных в package.json , достаточно перейти в корневую директорию проекта и выполнить в терминале команду npm run .
Но есть и ещё более удобный способ вывода списка скриптов. При его использовании нужный скрипт можно сразу же выбрать из списка и запустить. Для того чтобы воспользоваться этим способом работы со скриптами, нам понадобится глобально установить модуль ntl (Npm Task List):
npm i -g ntl
Затем в папке проекта нужно выполнить команду ntl . Она выведет список доступных скриптов и даст возможность выбрать скрипт, который нужно запустить. Вот как это выглядит.
Использование команды ntl
Эта возможность может оказаться очень кстати в том случае, если вы не знаете точно о том, какие скрипты есть в проекте. Хороша она и в тех случаях, когда программист хочет заменить ввод длинной команды для запуска скрипта на ввод короткой команды и быстрое нажатие ещё нескольких клавиш на клавиатуре.
8. Запуск pre-скриптов и post-скриптов
Возможно, вы знакомы со скриптами prebuild и postbuild , которые позволяют запускать некий код до и после запуска скрипта build . Такие вот pre- и post-скрипты можно определить и для любого другого скрипта. Включая те, описания которых добавляет в p ackage.json сам программист.
Это не только позволяет сделать код чище, но и способствует запуску pre- и post-скриптов в изоляции.
9. Управление версией приложения
Вместо того, чтобы вручную менять версию приложения, программист может воспользоваться специальными командами npm . Для того чтобы увеличить соответствующую часть номера версии приложения, можно воспользоваться командой npm version , за которой идёт major , minor или patch :
// 1.0.0 npm version patch // 1.0.1 npm version minor // 1.1.0 npm version major // 2.0.0
В зависимости от того, как часто вы обновляете своё приложение, вы можете сэкономить время, задав автоматическое увеличение номера версии каждый раз, когда развёртываете новую версию приложения. Например — так:
10. Редактирование package.json из командной строки
Файл package.json — это обычный json-файл, поэтому его можно редактировать прямо из командной строки с использованием утилиты json. Это открывает новые возможности в тех ситуациях, когда нужно изменить package.json , позволяя создавать собственные сокращённые варианты команд. Установим пакет json глобально:
npm install -g json
Затем утилиту json можно использовать для быстрого редактирования файла с помощью ключа -I . Например, для того чтобы добавить в файл новый скрипт foo со значением bar , можно воспользоваться такой командой:
json -I -f package.json -e 'this.scripts.foo="bar"'
В следующем разделе вы увидите более практичный пример использования утилиты json .
11. Автоматизация настройки и открытия репозитория
Если в вашем файле package.json есть запись «repository» — это значит, что вы можете открыть страницу репозитория в браузере, используемом в системе по умолчанию. Для этого применяется команда npm repo .
Если ваш проект уже подключён к удалённому репозиторию и у вас установлена утилита командной строки git , это значит, что выяснить адрес своего свой репозитория вы можете с помощью такой команды:
git config --get remote.origin.url
Но и это ещё не всё. Если вы, в соответствии с предыдущим советом, установили у себя утилиту json , то вы можете воспользоваться следующим скриптом для автоматического добавления корректных сведений о репозитории в package.json :
json -I -f package.json -e "this.repository=\"$(git config --get remote.origin.url)\""
12. Создание собственного скрипта, управляющего работой команды npm init
Теперь поговорим о решении более масштабной задачи. А именно, мы собираемся разработать собственный скрипт, управляющий работой команды npm init , который принимает URL GitHub-репозитория и автоматически отправляет в него первый коммит. Здесь мы поговорим о том, как создавать подобные скрипты. А в следующем разделе, который будет представлять наш последний совет, мы поговорим о работе с git .
Настроить поведение команды npm init можно с помощью файла .npm-init.js . Создадим такой файл в домашней директории текущего пользователя (в Windows это обычно C:/Users/ , а в Mac — /Users/ ). После этого выполним следующую команду, указывающую npm на то, где именно находится этот файл:
npm config set init-module ~\.npm-init.js
Прежде чем заниматься интеграцией c git , давайте посмотрим на простой пример файла .npm-init.js , в котором воспроизведены вопросы, которые система задаёт пользователю при использовании команды npm init без дополнительных настроек:
module.exports = < name: prompt('package name', basename || package.name), version: prompt('version', '0.0.0'), decription: prompt('description', ''), main: prompt('entry point', 'index.js'), repository: prompt('git repository', ''), keywords: prompt(function (s) < return s.split(/\s+/) >), author: prompt('author', 'Joe Bloggs (joebloggs.com)'), license: prompt('license', 'ISC') >
Каждый вопрос строится по следующему шаблону:
nameInPackage: prompt('nameInPrompt', 'defaultValue')
Для того чтобы указать некое значение и не задавать при этом вопрос пользователю, достаточно просто убрать метод prompt .
Если вы хотите вернуться к стандартным настройкам npm init — просто удалите файл .npm-init.js .
13. Отправка первого коммита в GitHub-репозиторий с помощью npm init
Для того чтобы выполнять команды git в файле .npm-init.js нам понадобится найти способ работы с командной строкой. Для этого можно воспользоваться модулем child_process . Мы подключаем его в верхней части файла, и, так как нам нужна только функция execSync , импортируем лишь её, воспользовавшись деструктурированием:
const < execSync >= require('child_process');
Кроме того, создадим вспомогательную функцию, которая выводит результаты работы нашей функции в консоль:
function run(func)
И, наконец, давайте создадим соответствующий prompt-блок для обработки URL GitHub-репозитория. Если URL имеется в распоряжении скрипта — мы создадим файл README.md и отправим в репозиторий первый коммит.
Итак, одним из элементов объекта module.exports файла .npm-init.js должен быть следующий код:
repository: prompt('github repository url', '', function (url) < if (url) < run('touch README.md'); run('git init'); run('git add README.md'); run('git commit -m "first commit"'); run(`git remote add origin $`); run('git push -u origin master'); return url; >)
Вот как после этого добавления должен выглядеть полный код файла .npm-init.js :
const < execSync >= require('child_process'); function run(func) < console.log(execSync(func).toString()) >module.exports = < name: prompt('package name', basename || package.name), version: prompt('version', '0.0.0'), decription: prompt('description', ''), main: prompt('entry point', 'index.js'), keywords: prompt(function (s) < return s.split(/\s+/) >), author: prompt('author', 'Joe Bloggs (joebloggs.com)'), license: prompt('license', 'ISC'), repository: prompt('github repository url', '', function (url) < if (url) < run('touch README.md'); run('git init'); run('git add README.md'); run('git commit -m "first commit"'); run(`git remote add origin $`); run('git push -u origin master'); return url; >), >
Вот как выглядит файл package.json , который система создаёт с использованием этого .npm-init.js :
< "name": "Custom npm init", "version": "0.0.0", "decription": "A test project, to demonstrate a custom npm init script.", "main": "index.js", "keywords": [], "author": "Joe Bloggs (joebloggs.com)", "license": "ISC", "repository": < "type": "git", "url": "git+https://github.com/JoeBloggs/custom.git" >, "bugs": < "url": "https://github.com/JoeBloggs/custom/issues" >, "homepage": "https://github.com/JoeBloggs/custom#readme" >
Настраивая процесс инициализации новых проектов, вы можете пойти и дальше. Например — сделать так, чтобы при создании проекта создавался бы и новый репозиторий для него.
Итоги
Надеюсь, этот материал помог вам увидеть то, чего можно достичь с помощью npm. Хочется верить в то, что вы нашли здесь что-то такое, что позволит вам работать продуктивнее — идёт ли речь об использовании сокращённых версий команд, о скриптах из package.json , или о настройке npm init в соответствии с вашими потребностями.
Уважаемые читатели! Автоматизируете ли вы работу с npm?
- Блог компании RUVDS.com
- Веб-разработка
- JavaScript