Извлечение CSS из компонентов React с помощью Laravel Mix

По умолчанию новая установка Laravel поставляется со скаффолдингом Vue, который предоставляет вам быструю отправную точку для написания ваших компонентов Vue и легко компилирует их в один готовый для браузера файл JavaScript. Это действительно помогает разработчикам Vue быстро запустить свой проект. Но, поскольку эта статья посвящена использованию React для внешнего интерфейса, предустановленная команда artisan оказывается полезной для замены стандартных лесов Vue на React.

При запуске любого нового приложения Laravel

php artisan preset react

После запуска этой команды Laravel попросит вас запустить

npm install && npm run dev

Это разрешит все зависимости, необходимые для преобразования вашего кода JSX в код JavaScript. Теперь, как мы все знаем, React не требует, чтобы мы следовали определенному способу структурирования наших проектов, но общий способ - это найти CSS, JS и тесты вместе в папках, сгруппированных по функциям.

common/

DisplayPicture.js

DisplayPicture.css

NewsFeed/

NewsFeed.js

NewsFeed.css

FeedStory.js

Config/

index.js

Config.js

UserConfig.js

AccountConfig.css

NewsFeedConfig.js

Но то, как Laravel структурирует ваш Javascript и CSS-код, сильно отличается от структуры React. Laravel имеет свою собственную папку ресурсов, в которую вы помещаете свой Javascript и код CSS в отдельные папки и указываете эти пути в файле Laravel webpack.mix.js.

resources/
assets/
js/

App.js

sass/

app.scss

let mix = require('laravel-mix');

mix.js('resources/assets/js/app.js', 'public/js')

.sass('resources/assets/sass/app.scss', 'public/css');

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

mix.options({ extractVueStyles: true });

в ваш файл webpack.config.js. Этот метод не работает для React. Мы должны использовать extract-text-webpack-plugin, чтобы извлечь CSS вручную. Вы можете установить его по npm.

npm install --save-dev extract-text-webpack-plugin

Теперь вам нужно изменить файл webpack.config.js, чтобы использовать этот плагин. Ваш конфигурационный файл будет выглядеть примерно так.

const { mix } = require('laravel-mix');

const path = require('path');

const ExtractTextPlugin = require("extract-text-webpack-plugin");

mix.react('resources/assets/src/app.js', 'public/assets/bundle');

mix.webpackConfig({

module: {

rules: [

{

test: /\.s[ac]ss$/,

loader: ExtractTextPlugin.extract({

fallback: 'style-loader',

use : [

{

loader : 'css-loader',

},

{

loader : 'postcss-loader',

},

{

loader : 'sass-loader',

}

]

})

}

]

},

plugins: [

new ExtractTextPlugin('[name].[contenthash].css')

],

devtool : 'source-map'

}).sourceMaps();

mix.options({

processCssUrls: false

});

Mix предоставляет полезный метод webpackConfig, который позволяет объединять любые короткие переопределения конфигурации Webpack. Теперь, если вам требуются файлы SASS / SCSS в ваших компонентах React, веб-пакет запустит на них загрузчики препроцессоров, чтобы перенести их в специальный CSS-файл, готовый для браузера.

Обновление: Важное примечание

Если вы используете laravel-mix 0,12 с webpack 2.0. *, Тогда вы сможете успешно создать свой код. Если вы используете Laravel 5.6, он поставляется с laravel-mix ^ 2.0 и webpack 3.11.0 выше конфигурации не удастся. Вы получите сообщение об ошибке

Неверный CSS после «… загрузки стилей»: ожидаемый 1 селектор или правило, было «var content = Requi»

Я потратил часы на отладку этой ошибки и обнаружил, что за кулисами микс использует пакет webpack-merge для объединения пользовательских правил и загрузчиков с конфигурацией webpack. В файле node_modules\laravel-mix\src\builder\WebpackConfig.js есть этот метод mergeCustomConfig (

mergeCustomConfig() {

if (Config.webpackConfig) {

this.webpackConfig = require('webpack-merge').smart(

this.webpackConfig,

Config.webpackConfig

);

const util = require('util');

console.log(util.inspect(this.webpackConfig, false, null))

}

}

Теперь в mix уже есть правило для тестирования / \. S [ac] ss $ / файлы. Если переданные вами ключи конфигурации объекта не соответствуют предопределенной конфигурации, он не объединит их, а в итоге добавит дублирующее правило для файлов SASS.

{

test: / \ .s[ac] ss$ /,

exclude: [ ],

loaders: ['style-loader', 'css-loader', 'sass-loader']

}, {

test: / \ .s[ac] ss$ /,

loader: [{

loader: 'C:\\xampp\\htdocs\\laravel-react\\node_modules\\extract-text-webpack-plugin\\dist\\loader.js',

options: {

omit: 1,

remove: true

}

},

{

loader: 'style-loader'

},

{

loader: 'css-loader'

},

{

loader: 'sass-loader'

}

]

}

Теперь, если вы используете старую версию laravel-mix, вы можете использовать вышеупомянутый файл конфигурации. Для более новой версии вам нужно добавить ключ exclude: [ ] в массив правил.

mix.webpackConfig({

module: {

rules: [

{

test: /\.s[ac]ss$/,

exclude : [], // For newer versions

loader: ExtractTextPlugin.extract({

fallback: 'style-loader',

use : [

{

loader : 'css-loader',

},

{

loader : 'sass-loader',

}

]

})

}

]

},

plugins: [

new ExtractTextPlugin('[name].css')

],

devtool : 'source-map'

});

Добавив ключ исключения в массив объектов правил, webpack-merge смог объединить его с существующей конфигурацией, и сборка кода прошла успешно.