scottcharlesworth / laravel-mix-polyfill

A Laravel Mix extension to include polyfills by using Babel, core-js, and regenerator-runtime
MIT License
50 stars 7 forks source link

support for mix.react #1

Closed r0one closed 5 years ago

r0one commented 5 years ago

Hi,

I've tried using .polyfill against the mix.react function. I thought it would work the same way as with mix.js but then I have this error:

Module build failed: Error: Couldn't find preset "@babel/preset-env" relative to directory "/home/romain/Documents/dev/simde/portail/resources/assets/react"

Do you think I just need to install and configure babel/preset-env somewhere? Or does it need a different implementation?

r0one commented 5 years ago

It looks like the package doesn't grab the correct dependencies. I'm trying to solve that manually.

scottcharlesworth commented 5 years ago

Hi @CdRom1

So I created a fresh Laravel Mix v4 project, and was able to compile React without any errors. @babel/preset-react was downloaded automatically as described here.

@babel/preset-env is a dependency of Laravel Mix 4.0, which is a dependency of this package - so it should already be available.

Do you have any further details on your setup so I can investigate? Did you use any of the extension options?

BryanK-AC commented 5 years ago

I got this error as well when my laravel-mix version was under 4.0.0 (was on 2.1.14). Went away when I followed the instructions to update to 4.0 here

scottcharlesworth commented 5 years ago

Yes, that will be the case.

This package is a plugin for Laravel Mix 4 and it is listed as a peer depencency. Since NPM v3 peer dependencies are never installed automatically, and instead you should receive the following warning when installing:

npm WARN laravel-mix-polyfill@1.0.0 requires a peer of laravel-mix@^4.0.0 but none is installed. You must install peer dependencies yourself.

More on peer dependencies can be read here and here.

I think that is the cause of this issue.

r0one commented 5 years ago

Okay, so I've upgrade laravel-mix and webpack to their latest versions (>4.0) and all dependencies seem to install fine, and I'm able to compile my code. However, the polyfill doesn't seem to work. When testing against firefox 38 like this :

mix.react('resources/assets/react/index.js', 'public/js/index.js').polyfill({
      enabled: true,
      useBuiltIns: "usage",
      targets: {"firefox": "38"}
   });

I've got the following error in console:

SyntaxError: class is a reserved identifier

The code throwing the error is the following:

class AspectRatio extends _react.Component {

So it looks like the code is not really well translated from ES6.

I am using the polyfill correctly? Should I implement other translations in Babel? @scottcharlesworth were you able to compile react with something like mix.react.polyfill or did you compile react manually (I mean, without using the laravel-mix automatic configuration of babel presets)?

Thanks everyone, I know this is potentially not an issue, but there are only a few solutions for using elegantly polyfills from laravel-mix without digging into webpack.

scottcharlesworth commented 5 years ago

So to test I:

  1. Downloaded Laravel 5.8
  2. Installed dependencies (php & node)
  3. Swapped the frontend scaffolding for react (using php artisan preset react)
  4. Added <div id="example"></div> to resources/views/welcome.blade.php
  5. Ran yarn prod to test compilation (it was successful), and checked result in browser

Next I installed Laravel Mix Polyfill. When doing so I received the following warning: warning " > @babel/preset-react@7.0.0" has unmet peer dependency "@babel/core@^7.0.0-0" so I installed it using: yarn add @babel/core@^7.4.0 --dev

My webpack.mix.js looks like the following:

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

require('laravel-mix-polyfill');

mix.react('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css')
   .polyfill({
      enabled: true,
      useBuiltIns: "usage",
      targets: {"firefox": "38"}
   });

To test polyfill, I used the following code for the example component:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

export default class Example extends Component {
    handleClick() {
      let arr = [1, 2, 3];
      console.log(arr.includes(2));
    }

    render() {
        return (
            <div className="container" onClick={() => this.handleClick()}>
                <div className="row justify-content-center">
                    <div className="col-md-8">
                        <div className="card">
                            <div className="card-header">Example Component</div>

                            <div className="card-body">
                                An example component!
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

if (document.getElementById('example')) {
    ReactDOM.render(<Example />, document.getElementById('example'));
}

Array.prototype.includes() wasn't available natively until Firefox 43 so is good as an example. When testing in Firefox 38, clicking div#example results in true being written to the console. Disabling polyfill results in the following message in its place: TypeError: arr.includes is not a function. This is the expected behaviour and proves the plugin can work with mix.react() (on a basic level at least).

As stated in the docs useBuiltIns: "usage" is experimental. Can you try changing this value to "entry" and require "@babel/polyfill" at the top of the entry point as described here?