Как связать Феникс c Вебпаком

Переведено в Докдоге – системе перевода технических текстов.

Работая над приложением, большое внимание в котором уделено фронтенду, можно облегчить себе жизнь с помощью Webpack, особенно если вам хочется добавить в проект React.

Webpack - довольно популярный на сегодняшний день инструмент, и Феникс, начиная с версии 1.4, будет поддерживать его прямо из коробки.

Но что делать, если хочется воспользоваться им уже сейчас, до выхода новой версии Феникса? Решение есть: заменить Brunch на Webpack.

Давайте посмотрим, как это можно сделать.

Настройка Webpack

Для начала целиком удалим конфигурацию Brunch из своего проекта.

В качестве наглядного примера будем рассматривать стандартное Феникс-приложение, использующее Brunch.

Поехали!

Первым делом удалим из зависимостей файла assets/package.json следующие библиотеки:

"babel-brunch"
"brunch"
"clean-css-brunch"
"uglify-js-brunch"

Теперь установим необходимые зависимости:

→ cd assets → npm install –save-dev babel-core babel-loader babel-preset-env 
→ npm install –save-dev webpack webpack-cli 
→ npm install –save-dev copy-webpack-plugin css-loader mini-css-extract-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin 
→ cd ..

Команда --save-dev добавит все вышеперечисленные зависимости в файл assets/package.json.

Откроем файл ещё раз и внесём изменения:

"deploy": "brunch build --production",
"watch": "brunch watch --stdin"

заменим на:

"deploy": "webpack --mode production",
"watch": "webpack --mode development --watch"

Это понадобится нам далее.

Теперь удалим файл assets/brunch-config.js.

Вместо него нужно будет создать assets/webpack.config.js, содержащий следующий код:

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = (env, options) => ({
    optimization: {
        minimizer: [
            new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
            new OptimizeCSSAssetsPlugin({})
        ]
    },
    entry: './js/app.js',
    output: {
        filename: 'app.js',
        path: path.resolve(__dirname, '../priv/static/js')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({ filename: '../css/app.css' }),
        new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
    ]
});

Добавим import css from "../css/app.css" в начало файла assets/js/app.js.

В config/dev.exs заменим

watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",

на

watchers: [node: ["node_modules/webpack/bin/webpack.js", "--mode", "development", "--watch-stdin",

Создадим файл assets/.babelrc со следующим содержимым:

{"presets": ["env"]}

Сюда можно добавить любую другую необходимую вам опцию. Их можно найти на странице библиотеки.

Примечание

Обратите внимание, что подключение файла assets/css/phoenix.css отсутствует в файле assets/css/app.css намеренно.

Это сделано по той причине, что стили Феникса 1.3 по умолчанию используют набор иконок “glyphicons”, шрифт для которых не включён в сам Феникс. Ранее ошибки не возникало, если не пытаться использовать данные символы, но с Webpack дела обстоят иначе. При обработке файла он пытается построить граф зависимостей и не может найти шрифты, вследствие чего мы получаем ошибку.

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

Скорее всего, в своем Феникс-приложении вы уже заменили стандартные стили на свои или что-то вроде Bootstrap, или Material Design.

В любом случае, в нашем примере мы не будем с этим заморачиваться.

Ну вот и всё. Теперь, если запустить веб-сервер, то проект, все стили и JavaScript должны работать как прежде.

Следующий шаг - настройка React.

Настройка React

Сначала установим дополнительные зависимости:

→ cd assets
→ npm install --save react react-dom
→ npm install --save-dev babel-preset-react
→ cd ..

“react” и “react-dom” нужны для работы самого React, а “babel-preset-react” - для того, чтобы появилась возможность использовать JSX в файлах JavaScript.

Допишем пресеты assets/.babelrc, чтобы они тоже содержали "react":

{"presets": ["env", "react"]}

Пока ни один стиль не задействован, добавим одно правило CSS для примера. (assets/css/app.css):

.jumbotron {
background: #eee;
text-align: center;
padding: 50px 0 50px;
}

Создадим assets/js/components/Jumbotron.js:

import React from "react";

const Jumbotron = () => {
    return (
        <div className="jumbotron">
            <h2>Welcome to Phoenix with Webpack and React</h2>
            <p className="lead">
                A productive web framework that<br />
                does not compromise speed and maintainability.
            </p>
        </div>
    )
};

export default Jumbotron;

Добавим в assets/js/app.js следующие строки:

import React from "react";
import ReactDOM from "react-dom";

import Jumbotron from './components/Jumbotron';

ReactDOM.render(<Jumbotron />, document.getElementById("react-app"));

И наконец, добавим элемент “react-app” на страницу.

В lib/<project_name>_web/templates/page/index.html.eex заменим всё на:

<div id="react-app"></div>

Готово. Запустите Феникс-сервер снова, и на странице должно появиться сообщение: “Welcome to Phoenix with Webpack and React”. Это значит, что компонент React подключён.

Заключение

Вот таким образом проводится настройка Webpack и React для проектов на Фениксе. Теперь вы сможете использовать React в своих приложениях, не дожидаясь релиза Феникса 1.4.

Рассмотренный пример можно найти по ссылке, а все его изменения - на GitHub.

© 2020 / Россия Любые мысли и вопросы пишите на elixir@wunsh.ru.