asmblah / uniter

🎉 PHP in the browser and Node.js => Docs: https://phptojs.com/
https://asmblah.github.io/uniter/
Other
446 stars 42 forks source link

Production Settings #49

Closed phpengine closed 4 years ago

phpengine commented 6 years ago

Hi Dude,

Long time no hear, How goes it? This might be quite a complex issue, but hopefully not :)

So, We've got Uniter running Isomorphic code pretty smoothly. It runs really fast in Desktop (Electron) but quite slowly sometimes on Cordova/Web. I think the reason is because the autoloader is using PHP Server style includes/requires to load classes.

This seems like a great way to work in development, as everything is always accessible to the developer plainly, but it can be quite slow in Web and especially Cordova.

So, the question is, what's the best way for me to turn that into "Production Settings". I was thinking, do I need to load absolutely everything at the beginning with a Progress Bar? Or a way of compression, minify, obfuscate or something, or would that break the Parser?

An example is here: http://www.isophp.org.uk , if you watch the firebug console/network while the page is loading, I think you'll see what I mean

Thanks, Dave

asmblah commented 6 years ago

Hi @phpengine,

I'm good thank you, how are you?

I've had a dig around on the page you mentioned and I notice it's fetching each PHP source file with a .fephp extension using an ajax request. I think the best way to speed things up for you would be to bundle all of your PHP files up using Webpack - there's a guide here which might be handy: https://uniter.github.io/docs/uniter/webpack_hello_world.html .

In your case you'll probably want to compile all of the front-end PHP files you're using into the JS bundle, which you can do by passing an option to PHPify with a list of globs like this: https://github.com/uniter/event-dispatcher-demo/blob/074ff5f/package.json#L12 . As you're not using Composer you won't need to include vendor/composer/* or anything else from vendor, of course. You'd also have to change the extension from .fephp to just .php for PHPify to pick them up, which should be ok as you won't then need the files to be downloadable as they'll be inside your compiled bundle. The extension is hardcoded here at the moment, so it's not configurable (but it could be) https://github.com/uniter/phpify/blob/8870b96/index.js#L23

Let me know how you get on! 😄

phpengine commented 6 years ago

Thanks, this looks great. I'm working on it now. I think I can get the build process to handle the file extension changes, though I may well keep the option open to alternatively send over a PR for PHPify if that works.

I'll keep you posted and hopefully be pinging over an efficiently loading page.

Thanks, Dave

phpengine commented 6 years ago

Hi @asmblah , I've got a fair amount of it running I think, as I've now replaced the unter.createEngine version with a binder style call. It's running PHP Code but I'm having an issue using requires from PHP. I've used the latest version of Webpack, its reporting all of the right php files being in there, with a .php extension. The old version created the phpEngine using uniter.createEngine, like this:

var uniter = require('uniter') ;
var phpEngine = uniter.createEngine('PHP') ;

function getFileData(path) {
    var filedata ;
    $.ajax({
        url: path,
        dataType: 'text',
        async: false,
        success: function (data, textStatus, jqXHR) {
            filedata = jqXHR.responseText ;
        },
        failure: function (data, textStatus, jqXHR) {
            filedata = jqXHR.responseText ;
        }
    });
    return filedata;
}

// Set up a PHP module loader
phpEngine.configure({
    include: function (path, promise) {
        var fd = getFileData(path) ;
        promise.resolve(fd);
    }
});

I was hoping to remove the Ajax by changing it to something like...

const binderModule = require('./binder.php')();

function getFileData(path) {
    return file_data[path] ;
}

// Set up a PHP module loader
binderModule.configure({
    include: function (path, promise) {
        var fd = getFileData(path) ;
        promise.resolve(fd);
    }
});

When I comment out the binderModule.configure section, the rest of it works. At this point, the JS Variable file_data contains all of the PHP files as raw text in a keyed array. The problem is that I get the error binderModule does not contain the method configure. If I can override the actual functionality of PHP's require at this point, I think it will work. I'll then also try to use the php files in the Webpack as opposed to that file_data array as its more scalable. Thanks

asmblah commented 6 years ago

Hi @phpengine,

Now that you have the PHP files compiled down and in your JS bundle, you should be able to remove the ajax fetching by just removing that binderModule.configure(...) call altogether - the PHPify library adds an include handler option for you that will include the compiled PHP module from the bundle.

If you open the compiled JS bundle, you should find a "virtual filesystem" in the form of a big switch(...) statement, something like this:

switch (path) {
    case handlePath("project/php/App/AppBootstrap.php"): return __webpack_require__(146);
    case handlePath("project/php/client.php"): return __webpack_require__(42);
    case handlePath("project/php/Plugin/Stuff/StuffPlugin.php"): return __webpack_require__(147);
    case handlePath("project/php/Plugin/Stuff/DependencyInjection/StuffExtension.php"): return __webpack_require__(148);
...

Hope this helps!

phpengine commented 6 years ago

Thanks very much, sorry I didn't respond earlier, working on it at the moment. I'll ping with an update as soon as, and hopefully a speedy loading page!

phpengine commented 6 years ago

Hi @asmblah , it took a while, but I have a very speedy Landing Page, which is really great. http://www.staging.isophp.org.uk/ . It loads the whole app in about 2 seconds. There's another problem arisen though, in that the same autoloader is unable to find some of the Classes in files loaded in the webpack...

Here is the Ajax version, the Controller/LandingPageController Class loads... http://www.devcloud.isophp.org.uk/

Here is the Webpack version, the Controller/LandingPageController Class cant be found... http://www.staging.isophp.org.uk/

Files that may help... The autoloader - https://github.com/PharaohTools/isophp_example/blob/development/core/init.php The controller - https://github.com/PharaohTools/isophp_example/blob/development/app/LandingPage/Controller/LandingPageController.php The webpack in staging - http://www.staging.isophp.org.uk/uniter_bundle/prod_bundle.js

I think it is something to do with Webpack, as it works via Ajax and in Zend. Also, the first few classes all load and execute correctly, it appears to be when using the controller Namespace maybe? All the Core Namespace classes load and execute fine.

So, the main issue is the following console error: uncaught exception: Error: PHP Fatal error: Class 'Controller\LandingPageController' not found

And I think If I can (Or maybe you can) solve that, it will be a complete set of Native performance Production settings. Please Help! Thanks, Dave

asmblah commented 6 years ago

Hi @phpengine,

After some investigation, I think this is caused by a bug in Uniter. It seems to be creating an invalid namespace with the empty string as its name, separate from the global namespace. In the meantime, you should be able to work around the bug by avoiding leading backslashes when referencing classes with strings - ie. for this particular issue, by making this change:

https://github.com/PharaohTools/isophp_example/blob/master/core/Core/Control.php#L11

$className = '\\Controller\\' . $ucf_control.'Controller' ;

to

$className = 'Controller\\' . $ucf_control.'Controller' ;

I'll keep you posted on a fix for the Uniter bug.

Cheers!

phpengine commented 6 years ago

Hi @asmblah - works smoothly: http://www.isophp.org.uk , it loads much faster in both Web and Cordova, opening in about 3-4 seconds for each with a complete application pre-transpiled. It's perfect, really fast native JS speed. It was already fast on Desktop, so I can only imagine it will be even faster, but I haven't built the Desktop apps yet. I'm happy for you to close this one, Thanks Dude! I haven't uploaded the speedy cordova versions of the mobile app yet, but ill ping comment link to it in the next couple of days.

asmblah commented 6 years ago

Hi @phpengine - perfect, glad it's all working for you now 👍 👍

asmblah commented 4 years ago

Closing as mentioned above - hope things are still working for you @phpengine!