Минимальный жизнеспособный Webpack, Babel, установка React БЕЗ «create-response-app»

Кажется, что большинство разработчиков, использующих React в последнее время, используют только «create-react-app» при запуске нового проекта. Это совершенно нормально для большинства проектов, но в какой-то момент вам, вероятно, понадобится внести некоторые изменения в Webpack по мере роста вашего проекта.

Это означает, что в конечном итоге вам нужно будет «извлечь» конфигурацию Webpack из проекта. Если вы ничего не делали с Webpack до того, как это может превратиться в головную боль, пытаясь выполнить то, что вам нужно.

В этой статье я покажу базовую настройку, которая объединит ваши файлы, создаст различные процессы сборки для разработки / производства, включая горячую загрузку, использует babel и изменит код сборки. Это, на мой взгляд, минимально жизнеспособная установка.

Мы собираемся построить это с нуля. БЕЗ КОТЛА! Я буду делать это с помощью Ubuntu. Mac тоже должен быть в порядке. В этом уроке я буду использовать Yarn, а не npm. Большинство команд очень похожи ... используйте npm, если хотите и вам это удобно.

Начнем с создания каталога нашего проекта:

mkdir min-viable
cd min-viable

Затем инициализируем наш package.json:

yarn init -y

Для нашей установки нам понадобятся следующие пакеты:

Зависимости:

  • реагировать
  • React-dom

DevDependencies:

  • веб-пакет
  • webpack-dev-server Обслуживает нашу сборку разработчика во время разработки
  • webpack-merge Позволяет нам объединять файлы конфигурации для Webpack (я обещаю, что позже будет иметь смысл!)
  • babel-core Нам нужен Babel, чтобы классы и т. д. работали в React. Нам также необходимо, чтобы в React были доступны другие функции, которых может не быть в старых браузерах.
  • babel-preset-es2015 Плагин для Babel, обеспечивающий возможность использования функций / синтаксиса ES6
  • babel-preset-react Позволяет нам использовать JSX и другие функции React вместе с ES6
  • css-loader Помогает Webpack находить и импортировать файлы css. Разрешает синтаксис импорта для таблиц стилей… аккуратно
  • babel-loader Загружает Babel в процесс сборки Webpack, который превращает ваш код ES6 в обратно совместимый код (по умолчанию ES5)
  • react-hot-loader Включает горячую загрузку во время разработки (страница перезагружается, когда вы вносите изменения в код)
  • clean-webpack-plugin Удаляет каталог сборки перед созданием новой сборки, гарантируя отсутствие каких-либо странных артефактов от предыдущих сборок
  • html-webpack-plugin Создает файл index.html, в который вы будете монтировать ваше приложение React.
  • uglifyjs-webpack-plugin Улучшает ваш код

Выполните следующую команду в своем терминале:

yarn add babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-2 clean-webpack-plugin css-loader html-webpack-plugin react-hot-loader style-loader uglifyjs-webpack-plugin webpack webpack-dev-server webpack-merge --dev

Это были только зависимости от разработки. Добавим наши реальные зависимости:

yarn add react react-dom

Ваш package.json теперь должен выглядеть примерно так:

{
  "name": "min-viable",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1",
    "clean-webpack-plugin": "^0.1.16",
    "css-loader": "^0.28.7",
    "html-webpack-plugin": "^2.30.1",
    "react-hot-loader": "^1.3.1",
    "style-loader": "^0.18.2",
    "uglifyjs-webpack-plugin": "^0.4.6",
    "webpack": "^3.6.0",
    "webpack-dev-server": "^2.8.2",
    "webpack-merge": "^4.1.0"
  },
  "dependencies": {
    "react": "^15.6.1",
    "react-dom": "^15.6.1"
  }
}

Затем давайте создадим наши файлы конфигурации. План состоит в том, чтобы иметь три файла конфигурации:

  • webpack.config.common.js
  • webpack.config.dev.js
  • webpack.config.prod.js

Файлы Dev и Prod будут использовать общие функции из файла Common.

Теперь давайте создадим все три из них в терминале. Они должны находиться в корневом каталоге проекта. Скоро мы их отредактируем:

touch webpack.config.common.js webpack.config.dev.js webpack.config.prod.js

Теперь ваша структура каталогов должна выглядеть следующим образом:

/node_modules
package.json
webpack.config.common.js
webpack.config.dev.js
webpack.config.prod.js
yarn.lock

Создать общий файл конфигурации

Начнем с webpack.config.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
  entry: {
    app: './src/index.js',
  },
plugins: [
    new CleanWebpackPlugin(['app']),
    new HtmlWebpackPlugin({
      title: 'Minimum-Viable',
      filename: 'index.html',
      template: './public/index.html',
    }),
  ],
module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              'es2015',
              'react',
            ],
          },
        },
        exclude: /node_modules/,
      },
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              'es2015',
              'react',
            ],
          },
        },
        exclude: /node_modules/,
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
        ],
      },
    ],
  },
output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'app'),
  },
};

Приведенный выше файл, конечно, требует некоторых пояснений. Я объясню каждое из свойств этого объекта ниже:

Вход

Webpack работает, проверяя, какие файлы вы откуда импортируете. Он берет каждый файл, на который была сделана ссылка из другого файла, и объединяет их в один файл (по крайней мере, по умолчанию… есть другие способы настройки Webpack). Webpack необходимо знать, где искать эти импортированные файлы. Чаще всего это будет index.js для приложений React. Он будет расположен в нашей папке «/ src», как и в create-response-app. Мы создадим файл index.js за минуту.

Плагины

Плагины делают вещи, явно не связанные с предварительной обработкой ваших файлов. В нашей минимально жизнеспособной настройке мы собираемся удалить каталог сборки и создать новый файл index.html в новом каталоге сборки. Обратите внимание, что мы указали шаблон в нашем HtmlWebpackPlugin. Мы сделаем это через минуту.

Модуль

Здесь мы включаем наши загрузчики и логику, определяющую, когда эти загрузчики должны запускаться. Загрузчики выполняют предварительную обработку наших файлов. В нашем случае мы запускаем наш код через babel для работы с ES5 и загрузки в стилях.

У нас есть «exclude», чтобы игнорировать node_modules, «test» с помощью регулярного выражения, чтобы решить, когда запускать загрузчик, и «use», чтобы объявить, какой загрузчик использовать. При внутреннем использовании мы устанавливаем предустановки Babel для использования.

Выход

Здесь следует объявить результирующее местоположение сборки. Здесь мы говорим Webpack, что хотим, чтобы результирующий пакет всех наших JS-файлов назывался «app.bundle.js» и что он должен быть помещен в каталог приложения (он будет создан Webpack).

Имя «app.bundle.js» происходит от части «[имя]», которая берется из имени свойства в записи (которая является приложением).

Создать файл конфигурации разработки

Последний созданный нами файл конфигурации будет использоваться как для производственной, так и для разрабатываемой сборки. Однако мы собираемся сделать еще несколько вещей в зависимости от того, находимся ли мы в режиме разработки или разработки.

Давайте создадим файл конфигурации разработки:

const merge = require('webpack-merge');
const common = require('./webpack.config.common.js');
const webpack = require('webpack');
const path = require('path');
module.exports = merge(common, {
  devtool: 'inline-source-map',
  devServer: {
    hot: true,
    contentBase: path.resolve(__dirname, 'app'),
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.jsx$/,
        use: 'react-hot-loader'
      }
    ]
  }
});

Пояснение к вышеуказанному файлу выглядит следующим образом:

слить

Мы берем наш файл webpack.config.common.js и объединяем его с нашим файлом dev. Держите его СУХИМ!

инструмент разработчика

Это позволяет нам видеть ошибки, которые соответствуют написанному нами коду. Помните, что когда приложение обслуживается, все сводится к минимуму и объединяется. Вам нужны исходные карты, чтобы можно было видеть, где находятся ошибки, поскольку вы написали код… не в комплекте. Это позволяет это.

devServer

Это позволяет вам использовать сервер разработки Webpack, который обеспечит горячую загрузку. «Hot» означает, что вы будете использовать «горячие» модули для горячей загрузки, а «contentBase» сообщает серверу, откуда передавать контент.

плагины

Мы включаем горячую загрузку с помощью этого плагина. Так же поступаем и с загрузчиком.

Создайте производственный файл конфигурации

Проделаем то же самое с нашим производственным файлом:

const merge = require('webpack-merge');
const common = require('./webpack.config.common.js');
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports = merge(common, {
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production'),
      },
    }),
    new UglifyJSPlugin(),
  ],
});

У нас есть процесс, аналогичный процессу разработки файла конфигурации. Вместо этого мы уродуем наш код и устанавливаем рабочий режим. Мы, конечно, объединяем наш производственный файл конфигурации с нашим общим.

Создайте наши отсутствующие файлы

Мы объявили некоторые пути в наших файлах конфигурации, которые мы еще не создали. Давайте исправим это сейчас (запускаем из корня проекта):

mkdir src
touch ./src/index.js
mkdir public
touch ./public/index.html

Каталог вашего проекта теперь должен выглядеть так:

/node_modules
/public
  index.html
/src
  index.js
package.json
webpack.config.common.js
webpack.config.dev.js
webpack.config.prod.js
yarn.lock

Давайте отредактируем наш файл index.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <title>Min-Viable</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="app"></div>
  </body>
</html>

Это будет действовать как шаблон, который будет помещаться в наш каталог сборки каждый раз, когда мы создаем сборку.

Давайте сделаем наш файл index.js:

import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
  <h1>Hey Buddy</h1>,
  document.getElementById('app'),
);
if (module.hot) {
  module.hot.accept();
}

Вы должны быть знакомы с этим кодом, если привыкли работать с React. Мы просто рендерим наше приложение в файл index.html, найдя div «#app». Затем нам нужно добавить немного кода внизу, чтобы включить горячую загрузку.

Теперь мы должны быть готовы, наконец, использовать нашу установку! Давайте попробуем запустить наш сервер и посмотрим, как он работает:

webpack-dev-server --config webpack.config.dev.js

В результате вы должны увидеть что-то похожее на это:

clean-webpack-plugin: /home/tovarishfin/medium-tuts/webpack/app has been removed.
Project is running at http://localhost:8080/
webpack output is served from /
Content not from webpack is served from /home/tovarishfin/medium-tuts/webpack/app
Hash: 626a4c5b5fbbc4074aff
Version: webpack 3.6.0
Time: 1562ms
        Asset       Size  Chunks                    Chunk Names
app.bundle.js    2.84 MB       0  [emitted]  [big]  app
   index.html  444 bytes          [emitted]         
  [50] (webpack)/hot/log.js 1.04 kB {0} [built]
  [84] (webpack)/hot/emitter.js 77 bytes {0} [built]
 [117] multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/index.js 52 bytes {0} [built]
 [118] (webpack)-dev-server/client?http://localhost:8080 7.27 kB {0} [built]
 [119] ./node_modules/url/url.js 23.3 kB {0} [built]
 [125] ./node_modules/strip-ansi/index.js 161 bytes {0} [built]
 [127] ./node_modules/loglevel/lib/loglevel.js 7.74 kB {0} [built]
 [128] (webpack)-dev-server/client/socket.js 1.04 kB {0} [built]
 [160] (webpack)-dev-server/client/overlay.js 3.71 kB {0} [built]
 [165] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
 [167] (webpack)/hot/dev-server.js 1.61 kB {0} [built]
 [168] (webpack)/hot/log-apply-result.js 1.31 kB {0} [built]
 [169] ./src/index.js 466 bytes {0} [built]
 [170] ./node_modules/react/react.js 56 bytes {0} [built]
 [186] ./node_modules/react-dom/index.js 59 bytes {0} [built]
    + 257 hidden modules
Child html-webpack-plugin for "index.html":
     1 asset
       [0] ./node_modules/html-webpack-plugin/lib/loader.js!./public/index.html 755 bytes {0} [built]
       [1] ./node_modules/lodash/lodash.js 540 kB {0} [built]
       [2] (webpack)/buildin/global.js 509 bytes {0} [built]
       [3] (webpack)/buildin/module.js 517 bytes {0} [built]
webpack: Compiled successfully.

Вы должны увидеть, как ваш новый проект запущен на «http: // localhost: 8080». Нажмите ctrl + c, чтобы выйти, когда будете готовы продолжить работу с этой удивительной и красивой страницы.

Давайте теперь проверим, что наша сборка для продакшена работает:

webpack --config ./webpack.config.prod.js

Теперь у вас должна быть папка приложения в корневом каталоге вашего проекта со следующей структурой:

/app
  app.bundle.js
  index.html

Взгляните на файл index.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <title>Min-Viable</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="app"></div>
  <script type="text/javascript" src="app.bundle.js"></script></body>
</html>

Вы можете видеть, что связанный файл из webpack был добавлен в файл index.html. Хорошо пойти!

Добавить скрипты в package.json

Давайте теперь упростим выполнение наших самых распространенных команд. Нам нужно будет обновить наш файл package.json:

{
  "name": "min-viable",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server --config ./webpack.config.dev.js --progress --colors",
    "build": "webpack --config ./webpack.config.prod.js --progress --colors"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1",
    "clean-webpack-plugin": "^0.1.16",
    "css-loader": "^0.28.7",
    "html-webpack-plugin": "^2.30.1",
    "react-hot-loader": "^1.3.1",
    "style-loader": "^0.18.2",
    "uglifyjs-webpack-plugin": "^0.4.6",
    "webpack": "^3.6.0",
    "webpack-dev-server": "^2.8.2",
    "webpack-merge": "^4.1.0"
  },
  "dependencies": {
    "react": "^15.6.1",
    "react-dom": "^15.6.1"
  }
}

Как видите, скрипты, добавленные в package.json, почти такие же, как мы только что протестировали. Мы добавили «- прогресс» и «- цвета», чтобы получать обновления по мере создания сборки.

Сохраните его и запустите:

npm start

Откройте в браузере адрес «http: // localhost: 8080» и попробуйте сохранить обновление в файл index.js…

Вы должны увидеть, что сборка воссоздана, и ваш браузер обновляется с изменениями, не обновляя страницу… хорошо!

Вы можете запустить сборку и отправить ее на рабочий сервер, но хотите использовать:

npm build

Теперь вы готовы приступить к созданию своего приложения без «create-response-app». Удачного взлома!