Что такое webpack

JavaScript - это функциональный язык программирования. Кодеры решают проблемы. Обычно вы берете большую проблему и разбиваете ее на более мелкие, которые можно решить. Как кодировщики, мы можем использовать для этого функции. Мы «разбиваем» нашу большую проблему на множество модулей более мелких проблем.

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

Одна из таких библиотек, используемых в веб-разработке, - это библиотека React. Вы, наверное, использовали утилиту create-react-app для быстрого запуска и запуска сайта. Мы слышали о webpack или babel, но эти термины, вероятно, знакомы только потому, что они часто встречаются, но действительно ли мы знаем, что они делают? Приложение create-react-app - отличная швейная машина, но, как разработчики, мы хотим знать, как взять эту нить и ткать ткань. Написание этой статьи предназначено для вас, чтобы вы создали свою собственную швейную машину, оттачивая свои навыки, чтобы стать лучшим разработчиком, и помогая вам лучше понять, как сшиваются нити.

При разработке веб-приложения есть много движущихся частей, есть языки разметки, такие как HTML; стили, применяемые через CSS; JavaScript, чтобы предоставить нам динамические веб-сайты; связь с серверами. Для того, чтобы они функционировали, они должны быть точно связаны друг с другом. Каждая часть должна знать свое отношение к другой. В небольшом веб-приложении мы можем отслеживать эти зависимости, но по мере того, как приложения становятся больше и делают все больше, поддерживать их вручную становится практически невозможно.

Webpack решает эту дилемму за нас. Нам не нужно беспокоиться о множестве зависимостей в нашем приложении; скорее, webpack будет отслеживать это, как кусочки головоломки, чтобы в конце сделать узнаваемую картинку. Все, что нам нужно сделать, это сказать webpack, что мы хотим, следуя стандарту конфигурации с определенными ключевыми элементами, представляющими интерес. Для нашей версии приложения create-react-app интересными точками являются вход, выход, модуль, инструмент разработчика и сервер разработчика. Объект модуля будет иметь набор правил, которые используются для интерпретации файлов из загрузчиков, которые мы будем устанавливать. Один из таких загрузчиков - babel.

Что такое Вавилон?

Сегодняшний JavaScript - это эволюция предыдущих версий JavaScript. Основное место, где работает JavaScript, - это браузеры. Эти браузеры могут понимать предыдущие версии синтаксиса JavaScript, но не самые последние. Как разработчик, вы можете использовать самый последний синтаксис, и вы можете это сделать, потому что Babel, который является компилятором, позволяет преобразовать ваш синтаксис в устаревший синтаксис, понятный браузеру. Это делается с помощью модуля babel / core и подключаемого модуля babel / preset-env. У Babel есть и другие возможности конвертации.

React использует JSX, который имеет синтаксис, подобный XML, но он не понимается и не реализуется ни одним браузером. Единственная причина, по которой существует JSX, - это облегчение написания древовидных структур с атрибутами, в основном HTML. Babel может транслировать JSX в браузер, он делает это с помощью устанавливаемого плагина babel / preset-react. Еще одна область, в которой babel может нам помочь, - это возможность писать более простой синтаксис.

Написание классов в React может стать громоздким, потому что нам нужно определить метод конструктора, вызвать super и, наконец, привязать методы внутри конструктора. Однако есть экспериментальный подключаемый модуль класса, который мы можем использовать для устранения привязки в конструкторе и использования стрелочной функции, чтобы все методы имели привязку this к экземпляру класса. Это приводит к более короткому синтаксису для объявления классов и методов в React. Это не JavaScript, это синтаксический сахар, который предоставляет плагин babel / plugin-scheme-class-properties.

Установка, установка и настройка

Теперь, когда у нас есть общее представление о том, что такое webpack и babel. Мы перейдем к созданию нашей собственной версии create-react-app.

  1. Создайте каталог с названием проекта, который вы создаете mkdir basics-react
  2. Запускаем npm init в терминале

Вы увидите серию запросов, в результате будет создан файл package.json, он будет выглядеть примерно так:

{
 "name": "basics-react",
  "version": "1.0.0",
  "description": "A back to basics approach for creating a react app",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Altaf Quadri",
  "license": "ISC"
}

3. Теперь мы установим response и реагируем dom через npm i react react-dom.

4. Создадим два дополнительных каталога src и общую папку через mkdir src public.

5. Давайте добавим папку и файл app.js mkdir src/components && touch src/app.js.

6. Мы добавим файл index.html touch public/index.html.

7. В нашем HTML-файле мы настроим шаблон, как показано ниже.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id='app'></div>
    <script src="bundle.js"></script>
</body>
</html>

8. Теперь в нашей папке компонентов мы создадим компонент HelloWorld.js и напишем простую программу hello world touch src/components/HelloWorld.js

import React, { Component } from 'react';
class HelloWorld extends Component {
    constructor(props) {
        super(props)
        this.state = {}
        this.handleClick = this.handleClick.bind(this)
    }
    handleClick() {
        alert('I am clicked! Yay')
    }
    render() {
        return (
            <div>
                <h1>Hello World</h1>
                <button onClick={this.handleClick}>Click Me!</button>
            </div>
        );
    }
}
export default HelloWorld;

9. А в app.js отрендерим программу, как показано ниже:

import React from 'react';
import ReactDOM from 'react-dom'
import HelloWorld from './components/HelloWorld'
ReactDOM.render(<HelloWorld />, document.getElementById('app'))

10. Ничего не будет работать, так как нам придется установить наши утилиты babel и webpack, вот список команд:

npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader webpack-dev-server webpack-cli webpack

11. Перейдем к скриптам и удалим тестовый скрипт, добавим два ключа JSON, пары значений.

"build": "webpack --mode production",

"server": "webpack-dev-server --open"

Когда мы настраиваем наш файл webpack, именно там webpack будет знать, что делать с этими скриптами. Теперь наш package.json должен выглядеть так:

{
  "name": "basics-react",
  "version": "1.0.0",
  "description": "A back to basics approach for creating a react app",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode production",
    "server": "webpack-dev-server --open"
  },
  "author": "Altaf Quadri",
  "license": "ISC",
  "dependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@babel/core": "^7.10.1",
    "@babel/preset-env": "^7.10.1",
    "@babel/preset-react": "^7.10.1",
    "babel-loader": "^8.1.0",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.11.0"
  }
}

12. Давайте настроим babel для использования предустановок. Сначала мы создадим файл конфигурации .babelrc touch .babelrc

В этом файле мы создадим объект JSON для настройки предустановок, как показано ниже:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

Теперь мы можем перейти к настройке webpack, сначала создайте файл

touch webpack.config.js

Затем мы введем в файл следующее:

const path = require('path')
module.exports = {
    entry: './src/app.js',
    output: {
        path: path.join(__dirname, 'public'),
        filename: 'bundle.js'
    },
    module: {
        rules: [{
            test: /\.js$/,
            use: 'babel-loader',
            exclude: /node_modules/
        }]
    },
    devtool: 'cheap-module-source-map',
    devServer: {
        contentBase: path.join(__dirname, 'public'),
        port: 3000
    }
}

Точка входа в нашем файле сообщает веб-пакету, где должно запускаться приложение. Здесь и начнется сборка. После того, как webpack построит наш граф зависимостей, ему понадобится место для вывода наших файлов. Выходной объект требует указания пути и имени файла. Ключ пути не работает с какими-либо специальными символами, как мы использовали для ввода, поэтому мы используем встроенный метод, устанавливая переменную const path = require('path'), а затем используем один из его методов, join, чтобы добавить его в папку, в которой мы хотим получить результат. Мы используем __dirname, чтобы получить абсолютный путь к папке, он зависит от компьютера, на котором вы находитесь. Имя файла будет помещено в указанный путь.

Следующим аргументом в нашем объекте является объект модуля, он сообщает webpack, как следует обращаться с конкретным модулем в вашем приложении, и они регулируются правилами, которые представляют собой массив. Содержимое правила - это объект, который разбит на три части: условия; полученные результаты; и вложенные правила.

То, что у нас есть выше, - это проверка всех файлов с расширением .js, полученная в результате нашего теста, регулярное выражение, которое ищет все файлы с расширением .js. Частично наше условие состоит в том, что мы исключаем модули узлов с файлами .js. Результат выполнения этих условий затем передается загрузчику babel, который сообщает webpack, как он должен работать с нашими модулями JavaScript. Позже мы добавим CSS или SCSS в массив правил, чтобы Weback знал, как объединить их в наш проект.

Ключ devtool помогает нам в отладке, предоставляя исходные карты нашего кода. Если в вашем приложении возникает ошибка, вы можете открыть инструменты Dev, и консоль сообщит вам, где произошла ошибка; однако, если вы не добавили ключ разработчика, он направит вас к скомпилированному файлу bundle.js, который не будет похож на написанный вами код, потому что это файл, который используется для связи с браузером. Нам нужен точный компонент и строка, в которой произошла ошибка, чтобы помочь нам в отладке. Добавление «cheap-module-source-map» к ключу devtool сделает именно это.

Теперь мы хотим обслуживать эти данные с помощью ключа devServer, где у нас есть объект с contentBase в качестве ключа в объекте, указывающем веб-пакету, откуда мы хотим обслуживать данные, и мы включили еще один ключ, чтобы сообщить ему, что он должен обслуживать содержимое на порт 3000. Запустим наш скрипт: npm run server. Веб-страница откроется с отображением Hello World. Давайте начнем настраивать наше приложение с добавления синтаксиса экспериментального класса в наш проект, а также возможности компилировать CSS / SCSS.

Примечание. Вы можете закрыть сервер для выполнения любых других установок, нажав Ctrl + C в терминале. Вам придется закрывать сервер каждый раз, когда он открыт, и требуется установка.

13. Мы будем run npm install --save-dev @babel/plugin-proposal-class-properties

14. Затем мы добавим плагин в наш файл .babelrc, используя синтаксис ниже:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

Давайте изменим наш компонент HelloWorld, чтобы он:

import React, { Component } from 'react';
class HelloWorld extends Component {
    state = {}
    handleClick = () => {
        alert('I am clicked! Yay')
    }
    render() {
        return (
            <div>
                <h1>Hello World</h1>
                <button onClick={this.handleClick}>Click Me!</button>
            </div>
        );
    }
}
export default HelloWorld;

Теперь у нас есть гораздо более короткий синтаксис с использованием нашего экспериментального плагина класса, который исключает использование конструктора и привязки его к экземпляру класса с помощью более короткого синтаксиса стрелочной функции. Приступим к добавлению нашего загрузчика CSS / SCSS.

15. Сначала мы установим наши пакеты:

npm install style-loader css-loader sass-loader node-sass --save-dev

Затем мы изменим наш массив правил, добавив объект, который сообщает веб-пакету, что делать, если он встречает файл с расширением .css или .scss, используя выражение регулярного выражения /.s?css$/, и используйте загрузчики в в следующем порядке ['style-loader', 'css-loader', 'sass-loader'] путем преобразования любых типов файлов .scss в css, а затем возьмите этот CSS и вставьте его в загрузчик стилей, чтобы связать его с нашим кодом . Наш webpack.config.js теперь выглядит так:

const path = require('path')
module.exports = {
    entry: './src/app.js',
    output: {
        path: path.join(__dirname, 'public'),
        filename: 'bundle.js'
    },
    module: {
        rules: [{
            test: /\.js$/,
            use: 'babel-loader',
            exclude: /node_modules/
        }, 
        {
            test: /\.s?css$/,
            use: ['style-loader', 'css-loader', 'sass-loader']
        }]
    },
    devtool: 'cheap-module-source-map',
    devServer: {
        contentBase: path.join(__dirname, 'public'),
        port: 3000
    }
}

16. Мы создадим каталог стилей к mkdir src/styles

17. Затем мы добавим файл HelloWorld.css touch src/styles/HelloWorld.css.

.title {
  color: green;
}

18. Затем мы добавим файл HelloWorld.scss touch src/styles/HelloWorld.scss.

.button {
  color: red;
}

Затем мы внесем поправки в наш компонент HelloWorld, добавив созданные нами имена классов, а также импортируем в компонент наши файлы .css и .scss.

import React, { Component } from 'react';
import '../styles/HelloWorld.css'
import '../styles/HelloWorld.scss'
class HelloWorld extends Component {
    state = {}
    handleClick = () => {
        alert('I am clicked! Yay')
    }
    render() {
        return (
            <div>
                <h1 className='title'>Hello World</h1>
                <button className='button'
                    onClick={this.handleClick}>Click Me!</button>
            </div>
        );
    }
}
export default HelloWorld;

Давайте запустим наш сервер и убедимся, что он работает. Вы можете запустить npm run server в терминале.

Наша последняя настройка приложения - использовать HtmlWebpackPlugin, чтобы наши HTML-файлы были созданы для нас. Однако мы добавим шаблон на тот случай, если мы захотим добавить какие-либо теги скрипта в наш HTML-файл.

19. Мы возьмем наш исходный файл index.html, который находится в нашей общей папке, и переместим его в нашу папку src.

20. Давайте установим плагин.

npm install --save-dev html-webpack-plugin

  1. Измените наш файл webpack.config.js, как показано ниже:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry: './src/app.js',
    output: {
        path: path.join(__dirname, 'public'),
        filename: 'bundle.js'
    },
    module: {
        rules: [{
            test: /\.js$/,
            exclude: /node_modules/,
            use: 'babel-loader'
        },
        {
            test: /\.s?css$/,
            use: ['style-loader', 'css-loader', 'sass-loader']
        }]
    },
    devtool: 'cheap-module-source-map',
    devServer: {
        contentBase: path.join(__dirname, 'public'),
        port: 3000
    },
    plugins: [new HtmlWebpackPlugin({
        template: './src/index.html'
    })]
}

Нам потребуется html-webpack-plugin, и мы добавим ключ плагинов, который имеет значение массива, в этом массиве мы создадим экземпляр плагина HtmlWebpack и передадим объект шаблона, указывающий на исходный файл index.html .

Когда мы запустим наш скрипт npm run build, мы увидим, что все файлы, включая html-файл, обслуживаются веб-пакетом.

Бонус

Мне очень нравится ESLint из приложения create response, поэтому я устанавливаю его как пакет, поэтому вам придется установить:

  1. загрузчик eslint npm install eslint-loader --save-dev
  2. Затем следующее из пакета создания приложения реагирования
npm install --save-dev eslint-config-react-app [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]

3. Создайте файл .eslintrc и коснитесь .eslintrc.

{
  "extends": "react-app"
}

4. Затем настройте файл webpack.config.js для использования eslint-loader. Примечание. Мы преобразовали значение use в массив. Наш последний экспорт модуля выглядит следующим образом:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry: './src/app.js',
    output: {
        path: path.join(__dirname, 'public'),
        filename: 'bundle.js'
    },
    module: {
        rules: [{
            test: /\.js$/,
            exclude: /node_modules/,
            use: ['babel-loader', 'eslint-loader']
        },
        {
            test: /\.s?css$/,
            use: ['style-loader', 'css-loader', 'sass-loader']
        }]
    },
    devtool: 'cheap-module-source-map',
    devServer: {
        contentBase: path.join(__dirname, 'public'),
        port: 3000
    },
    plugins: [new HtmlWebpackPlugin({
        template: './src/index.html'
    })]
}

Окончательные версии webpack.config.js и package.json:

Теперь у вас есть адаптированная версия базового приложения React с использованием webpack и babel. Когда мы используем такой инструмент, как create-react-app, мы воспринимаем многое как должное, но, надеюсь, прочитав это, вы лучше понимаете, что происходит под капотом. Теперь ваша очередь реализовать приложение basics-react в вашем любимом редакторе.

Ссылка на репозиторий github: https://github.com/altafmquadri/basics-react. Не стесняйтесь клонировать и использовать.