Назад

Рецепт: Webpack 4 + React + Babel 7 = ❤️

Сегодня я собрал волю в кулак и, все-таки, перешел в своем давнем React проекте с Webpack 2 на Webpack 4. Не скажу, что это было сложно, но потратить немного времени, все же, пришлось. Признаюсь честно, это был мой уже второй подход. Я пытался это сделать когда он только вышел, но тогда быстро все не взлетело и я решил отложить. Теперь, когда все грабли уже успешно пройдены, то я решил написать эту небольшую статью, чтобы, возможно, облегчить вам страдания.

Пожалуй, главная проблема с которой я столкнулся - это переход на Babel 7. При переходе на седьмую версию изменился принцип именования пакетов и простым проставлением новых версий в package.json отделаться не удалось. В итоге мой package.json, а если быть точнее, то секция devDependencies, выглядит теперь примерно так:

...
"devDependencies": {
    "@babel/cli": "^7.1.2",
    "@babel/core": "^7.1.2",
    "@babel/plugin-proposal-class-properties": "^7.1.0",
    "@babel/polyfill": "^7.0.0",
    "@babel/preset-env": "^7.1.0",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.4",
    "css-loader": "^1.0.0",
    "mini-css-extract-plugin": "^0.4.4",
    "node-sass": "^4.9.4",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "uglifyjs-webpack-plugin": "^2.0.1",
    "url-loader": "^1.1.2",
    "webpack": "^4.21.0",
    "webpack-cli": "^3.1.2"
}
...

Для конфигурации Babel я использую .babelrc. В моем случае он выглядит так:

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

Если говорить про сам Webpack, то, ко всему прочему, теперь добавился новый пакет - webpack-cli. Что это такое, в принципе, понятно из названия, но изначально я не ставил его. Когда я запустил свои старые скрипты, то они успешно запустились, хотя я и получил предложение поставить webpack-cli.

Фаил webpack.config.js в моем случае выглядит так:

const path = require('path');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const devMode = process.env.NODE_ENV !== 'production';
const plugins = [
    new MiniCssExtractPlugin({
        filename: '[name].css'
    })
];

if (process.env.NODE_ENV === 'production') {
    plugins.push(new UglifyJSPlugin());
}

const config = {
    mode: process.env.NODE_ENV === 'production' || 'development',
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                include: [
                    path.resolve(__dirname, "src/frontend")
                ],
                enforce: "pre",
                loader: "babel-loader"
            },
            {
                test: /\.(sa|sc|c)ss$/,
                use: [
                    devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
                    'css-loader',
                    //'postcss-loader',
                    'sass-loader',
                ],
            },
            {
                test: /\.(png|woff|woff2|eot|ttf|svg)$/,
                use: 'url-loader'
            }
        ]
    },
    performance: {
        hints: "warning",
    },
    devtool: "source-map",
    resolve: {
        modules: [
            path.resolve(__dirname),
            'node_modules'
        ],
        extensions: ['.js', '.jsx', '.css', '.scss']
    },
    plugins
}

module.exports = [
    Object.assign({}, config, {
        entry: path.resolve(__dirname, './src/frontend/index.js'),
        output: {
            path: path.resolve(__dirname, './public/assets/')
        }
    })
];

Как вы, возможно, заметили, я закомментировал строку postcss-loader'. Раньше я использовал его, чтобы применять autoprefixer, но теперь необходимость в этом отпала. Если в вашем случае он все же нужен, то раскомментируйте эту строку и у вас обязательно должен быть фаил postcss.config.js в корне проекта. Как минимум он должен выглядеть так:

module.exports = {};

Смысла в этом, конечно же, никакого, так как он просто ничего не будет делать. Подробную информацию о настройке PostCSS вы можете почитать на официальной странице в Github.

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

Вот и все. Теперь Webpack готов. У меня есть два скрипта, которые я использую для разработки и для создания production билда:

...
"scripts": {
    "frontend:dev": "NODE_ENV=development webpack --watch",
    "frontend:build": "NODE_ENV=production webpack -p"
},
...

Надеюсь, что вам помогло это руководство. Если у вас какие-то вопросы - пишите. Мои контакты вы можете найти на главной странице.

Возможно вам будет интересно:

Как повысить производительность React приложений

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

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

Рецепт: Webpack 4 + React + Babel 7 = ❤️

Сегодня я собрал волю в кулак и, все-таки, перешел в своем давнем React проекте с Webpack 2 на Webpack 4. Не скажу, что это было сложно, но потратить немного времени, все же, пришлось. Признаюсь честно, это был мой уже второй подход. Я пытался это сделать когда он только вышел, но тогда быстро все не взлетело и я решил отложить. Теперь, когда все грабли уже успешно пройдены, то я решил написать эту небольшую статью, чтобы, возможно, облегчить вам страдания.