├── README.md ├── package.json └── setup └── webpack.config.js /README.md: -------------------------------------------------------------------------------- 1 | > ### ⚠️ DEPRECATED—please use the `mix.react()` method included by default in [Laravel Mix](https://laravel.com/docs/mix#react). 2 | 3 | # laravel-mix-react 4 | 5 | Easy alternative Laravel Mix configuration for projects using React. Includes the babel loaders and Webpack configuration file 6 | you need to get started. (Please note that this is NOT a drop-in replacement for Laravel Mix -- you will still need to 7 | include the `laravel-mix` package along with this one!) 8 | 9 | ## Installation 10 | 11 | Run `npm install --save-dev laravel-mix-react` or `yarn add --dev laravel-mix-react` 12 | 13 | In your project's `package.json`, update all references to `--config="node_modules/laravel-mix/setup/webpack.config.js"` 14 | within the "scripts" to point to `node_modules/laravel-mix-react/setup/webpack.config.js`. 15 | 16 | ## Advanced configuration 17 | 18 | If you need to make further changes to Webpack, run `cp node_modules/laravel-mix-react/setup/webpack.config.js ./` in your 19 | terminal. This will copy the modified `webpack.config.js` into the root of your project. Modify your config as needed, and then 20 | remove the `--config="node_modules/laravel-mix-react/setup/webpack.config.js"` lines from your `package.json` file. 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel-mix-react", 3 | "version": "1.0.1", 4 | "description": "Alternate Laravel Mix webpack configuration for React projects", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Samantha Geitz ", 10 | "license": "MIT", 11 | "dependencies": { 12 | "babel-loader": "^6.2.10", 13 | "babel-preset-es2015": "^6.22.0", 14 | "babel-preset-react": "^6.22.0", 15 | "babel-preset-stage-1": "^6.22.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /setup/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack'); 3 | var Mix = require('laravel-mix').config; 4 | var plugins = require('laravel-mix').plugins; 5 | 6 | 7 | /* 8 | |-------------------------------------------------------------------------- 9 | | Mix Initialization 10 | |-------------------------------------------------------------------------- 11 | | 12 | | As our first step, we'll require the project's Laravel Mix file 13 | | and record the user's requested compilation and build steps. 14 | | Once those steps have been recorded, we may get to work. 15 | | 16 | */ 17 | 18 | Mix.initialize(); 19 | 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Webpack Context 24 | |-------------------------------------------------------------------------- 25 | | 26 | | This prop will determine the appropriate context, when running Webpack. 27 | | Since you have the option of publishing this webpack.config.js file 28 | | to your project root, we will dynamically set the path for you. 29 | | 30 | */ 31 | 32 | module.exports.context = Mix.Paths.root(); 33 | 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Webpack Entry 38 | |-------------------------------------------------------------------------- 39 | | 40 | | We'll first specify the entry point for Webpack. By default, we'll 41 | | assume a single bundled file, but you may call Mix.extract() 42 | | to make a separate bundle specifically for vendor libraries. 43 | | 44 | */ 45 | 46 | module.exports.entry = Mix.entry(); 47 | 48 | 49 | /* 50 | |-------------------------------------------------------------------------- 51 | | Webpack Output 52 | |-------------------------------------------------------------------------- 53 | | 54 | | Webpack naturally requires us to specify our desired output path and 55 | | file name. We'll simply echo what you passed to with Mix.js(). 56 | | Note that, for Mix.version(), we'll properly hash the file. 57 | | 58 | */ 59 | 60 | module.exports.output = Mix.output(); 61 | 62 | 63 | /* 64 | |-------------------------------------------------------------------------- 65 | | Rules 66 | |-------------------------------------------------------------------------- 67 | | 68 | | Webpack rules allow us to register any number of loaders and options. 69 | | Out of the box, we'll provide a handful to get you up and running 70 | | as quickly as possible, though feel free to add to this list. 71 | | 72 | */ 73 | 74 | module.exports.module = { 75 | rules: [ 76 | 77 | { 78 | test: /\.jsx?$/, 79 | exclude: /(node_modules|bower_components)/, 80 | loader: 'babel-loader' + Mix.babelConfig(), 81 | query: { 82 | babelrc: false, 83 | presets: [ 84 | 'es2015', 85 | 'react', 86 | 'stage-1' 87 | ] 88 | } 89 | }, 90 | 91 | { 92 | test: /\.(png|jpg|gif)$/, 93 | loader: 'file-loader', 94 | options: { 95 | name: '[name].[ext]?[hash]' 96 | } 97 | }, 98 | 99 | { 100 | test: /\.(woff2?|ttf|eot|svg|otf)$/, 101 | loader: 'file-loader', 102 | options: { 103 | name: 'fonts/[name].[ext]?[hash]', 104 | publicPath: '/' 105 | } 106 | } 107 | ] 108 | }; 109 | 110 | 111 | if (Mix.cssPreprocessor) { 112 | Mix[Mix.cssPreprocessor].forEach(toCompile => { 113 | let extractPlugin = new plugins.ExtractTextPlugin( 114 | Mix.cssOutput(toCompile) 115 | ); 116 | 117 | module.exports.module.rules.push({ 118 | test: new RegExp(toCompile.src.path), 119 | loader: extractPlugin.extract({ 120 | fallbackLoader: 'style-loader', 121 | loader: [ 122 | 'css-loader', 123 | 'postcss-loader', 124 | 'resolve-url-loader', 125 | (Mix.cssPreprocessor == 'sass') ? 'sass-loader?sourceMap&precision=8' : 'less-loader' 126 | ] 127 | }) 128 | }); 129 | 130 | module.exports.plugins = (module.exports.plugins || []).concat(extractPlugin); 131 | }); 132 | } 133 | 134 | 135 | 136 | /* 137 | |-------------------------------------------------------------------------- 138 | | Resolve 139 | |-------------------------------------------------------------------------- 140 | | 141 | | Here, we may set any options/aliases that affect Webpack's resolving 142 | | of modules 143 | | 144 | */ 145 | 146 | module.exports.resolve = { 147 | extensions: ['*', '.js', '.jsx'], 148 | }; 149 | 150 | 151 | 152 | /* 153 | |-------------------------------------------------------------------------- 154 | | Stats 155 | |-------------------------------------------------------------------------- 156 | | 157 | | By default, Webpack spits a lot of information out to the terminal, 158 | | each you time you compile. Let's keep things a bit more minimal 159 | | and hide a few of those bits and pieces. Adjust as you wish. 160 | | 161 | */ 162 | 163 | module.exports.stats = { 164 | hash: false, 165 | version: false, 166 | timings: false, 167 | children: false, 168 | errors: false 169 | }; 170 | 171 | module.exports.performance = { hints: false }; 172 | 173 | 174 | 175 | /* 176 | |-------------------------------------------------------------------------- 177 | | Devtool 178 | |-------------------------------------------------------------------------- 179 | | 180 | | Sourcemaps allow us to access our original source code within the 181 | | browser, even if we're serving a bundled script or stylesheet. 182 | | You may activate sourcemaps, by adding Mix.sourceMaps(). 183 | | 184 | */ 185 | 186 | module.exports.devtool = Mix.sourcemaps; 187 | 188 | 189 | 190 | /* 191 | |-------------------------------------------------------------------------- 192 | | Webpack Dev Server Configuration 193 | |-------------------------------------------------------------------------- 194 | | 195 | | If you want to use that flashy hot module replacement feature, then 196 | | we've got you covered. Here, we'll set some basic initial config 197 | | for the Node server. You very likely won't want to edit this. 198 | | 199 | */ 200 | module.exports.devServer = { 201 | historyApiFallback: true, 202 | noInfo: true, 203 | compress: true 204 | }; 205 | 206 | 207 | 208 | /* 209 | |-------------------------------------------------------------------------- 210 | | Plugins 211 | |-------------------------------------------------------------------------- 212 | | 213 | | Lastly, we'll register a number of plugins to extend and configure 214 | | Webpack. To get you started, we've included a handful of useful 215 | | extensions, for versioning, OS notifications, and much more. 216 | | 217 | */ 218 | 219 | module.exports.plugins = (module.exports.plugins || []).concat([ 220 | new webpack.ProvidePlugin(Mix.autoload || { 221 | jQuery: 'jquery', 222 | $: 'jquery', 223 | jquery: 'jquery', 224 | 'window.jQuery': 'jquery' 225 | }), 226 | 227 | new plugins.FriendlyErrorsWebpackPlugin(), 228 | 229 | new plugins.StatsWriterPlugin({ 230 | filename: "mix-manifest.json", 231 | transform: Mix.manifest.transform, 232 | }), 233 | 234 | new plugins.WebpackMd5HashPlugin(), 235 | 236 | new webpack.LoaderOptionsPlugin({ 237 | minimize: Mix.inProduction, 238 | options: { 239 | postcss: [ 240 | require('autoprefixer') 241 | ], 242 | context: __dirname, 243 | output: { path: './' } 244 | } 245 | }) 246 | ]); 247 | 248 | 249 | 250 | if (Mix.notifications) { 251 | module.exports.plugins.push( 252 | new plugins.WebpackNotifierPlugin({ 253 | title: 'Laravel Mix', 254 | alwaysNotify: true, 255 | contentImage: Mix.Paths.root('node_modules/laravel-mix/icons/laravel.png') 256 | }) 257 | ); 258 | } 259 | 260 | 261 | module.exports.plugins.push( 262 | new plugins.WebpackOnBuildPlugin( 263 | () => Mix.events.fire('build') 264 | ) 265 | ); 266 | 267 | 268 | if (Mix.versioning) { 269 | Mix.versioning.record(); 270 | 271 | module.exports.plugins.push( 272 | new plugins.WebpackOnBuildPlugin(() => { 273 | Mix.versioning.prune(Mix.publicPath); 274 | }) 275 | ); 276 | } 277 | 278 | 279 | if (Mix.combine || Mix.minify) { 280 | module.exports.plugins.push( 281 | new plugins.WebpackOnBuildPlugin(() => { 282 | Mix.concatenateAll().minifyAll(); 283 | }) 284 | ); 285 | } 286 | 287 | 288 | if (Mix.copy) { 289 | Mix.copy.forEach(copy => { 290 | module.exports.plugins.push( 291 | new plugins.CopyWebpackPlugin([copy]) 292 | ); 293 | }); 294 | } 295 | 296 | 297 | if (Mix.js.vendor) { 298 | module.exports.plugins.push( 299 | new webpack.optimize.CommonsChunkPlugin({ 300 | names: [Mix.js.base + '/vendor', Mix.js.base + '/' + 'manifest'], 301 | minChunks: Infinity 302 | }) 303 | ); 304 | } 305 | 306 | 307 | if (Mix.inProduction) { 308 | module.exports.plugins = module.exports.plugins.concat([ 309 | new webpack.DefinePlugin({ 310 | 'process.env': { 311 | NODE_ENV: '"production"' 312 | } 313 | }), 314 | 315 | new webpack.optimize.UglifyJsPlugin({ 316 | sourceMap: true, 317 | compress: { 318 | warnings: false 319 | } 320 | }) 321 | ]); 322 | } 323 | 324 | 325 | /* 326 | |-------------------------------------------------------------------------- 327 | | Mix Finalizing 328 | |-------------------------------------------------------------------------- 329 | | 330 | | Now that we've declared the entirety of our Webpack configuration, the 331 | | final step is to scan for any custom configuration in the Mix file. 332 | | If mix.webpackConfig() is called, we'll merge it in, and build! 333 | | 334 | */ 335 | Mix.finalize(module.exports); 336 | --------------------------------------------------------------------------------