Last active
June 11, 2018 00:43
-
-
Save mblarsen/b9cddae32ef0a3cfb93f7ed71720fc60 to your computer and use it in GitHub Desktop.
Laravel and Webpack (with webpack-dev-server)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Supawdog\Console\Commands; | |
use Illuminate\Console\Command; | |
use Symfony\Component\Process\ProcessUtils; | |
use Symfony\Component\Console\Input\InputOption; | |
use Symfony\Component\Process\PhpExecutableFinder; | |
class WebpackCommand extends Command | |
{ | |
protected $signature = 'webpack {--config=webpack.config.js}'; | |
protected $description = 'Serve the application on the PHP development server'; | |
public function fire() | |
{ | |
chdir($this->laravel->publicPath()); | |
$config_path = $this->option('config'); | |
list($host, $port) = $this->getHostAndPort($config_path); | |
$this->info("Backend started on http://{$host}:{$port}/ as proxy"); | |
$this->info("Client running on " . $this->getClientUrl($config_path)); | |
$binary = ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false)); | |
$base = ProcessUtils::escapeArgument($this->laravel->basePath()); | |
passthru("WEBPACK_DEV=running {$binary} -S {$host}:{$port} {$base}/server.php"); | |
} | |
protected function getClientUrl(string $config_path) : string | |
{ | |
$config = $this->getConfig($config_path); | |
return array_get($config, 'output.publicPath'); | |
} | |
protected function getHostAndPort(string $config_path) : array | |
{ | |
$config = $this->getConfig($config_path); | |
$proxies = array_get($config, 'devServer.proxy'); | |
$first_proxy = array_first(array_values($proxies)); | |
$host = parse_url($first_proxy, PHP_URL_HOST); | |
$port = parse_url($first_proxy, PHP_URL_PORT); | |
return [$host, $port]; | |
} | |
protected function getConfig(string $config_path) : array | |
{ | |
static $config; | |
if (is_null($config)) { | |
if (strpos($config_path, '/') !== 0) { | |
$base = $this->laravel->basePath(); | |
$config_path = "/$base/$config_path"; | |
} | |
// Run through node to "compile" the config | |
exec("node -e 'console.log(JSON.stringify(require(\"$config_path\")))'", $json); | |
$config = json_decode($json[0], true); | |
} | |
return $config; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* A replacement for elixir() that will work for both typical laravel development where the | |
* blade file will include links and references to stylesheets and javascript, and it will | |
* work for when you run laravel as the backend in a proxy setup with webpack-dev-server | |
* as the controller. | |
*/ | |
if (! function_exists('webpack')) { | |
function webpack($resource, $is_entry = false) : string | |
{ | |
static $manifest; | |
$is_webpack_dev = !!getenv('WEBPACK_DEV'); | |
$type = dirname($resource); | |
$chunk = basename($resource); | |
// If in webpack dev mode only return entries | |
if ($is_webpack_dev) { | |
if (! $is_entry) { | |
return ''; | |
} | |
return call_user_func("webpack__$type", "$resource.$type"); | |
} | |
if (is_null($manifest)) { | |
$manifest = json_decode(file_get_contents(public_path('rev-manifest.json')), true); | |
} | |
if (isset($manifest[$chunk])) { | |
$assets = $manifest[$chunk]; | |
// If only one it is a string | |
if (is_string($manifest[$chunk])) { | |
$assets = [$assets]; | |
} | |
// Match chunk and type | |
$asset = array_first($assets, function ($asset) use ($resource) { | |
return strpos($asset, $resource) === 0; | |
}); | |
return call_user_func("webpack__$type", $asset); | |
} | |
throw new InvalidArgumentException("Resource {$resource} is not defined in asset manifest."); | |
} | |
function webpack__js($url) | |
{ | |
return "<script type=\"text/javascript\" src=\"$url\"></script>"; | |
} | |
function webpack__css($url) | |
{ | |
return "<link rel=\"stylesheet\" href=\"$url\"/>"; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<meta name="csrf-token" content="{{ csrf_token() }}"> | |
<title>{{ config('app.name', 'Supaw Dog') }}</title> | |
{!! webpack('css/commons') !!} <!-- not marked as entry --> | |
@stack('styles') | |
<script> | |
window.Supawdog = <?php echo json_encode([ | |
'csrfToken' => csrf_token() | |
]); ?> | |
</script> | |
</head> | |
<body> | |
<div id="app"> | |
@yield('content') | |
</div> | |
@yield('footer') | |
{!! webpack('js/commons') !!} <!-- not marked as entry --> | |
@stack('scripts') | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@extends('layouts.app') | |
@push('styles') | |
{!! webpack('css/app') !!} <!-- not marked as entry --> | |
@endpush | |
@push('scripts') | |
{!! webpack('js/app', true) !!} <!-- this is the entry point --> | |
@endpush |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Vist this URL in browser | |
config.output.publicPath = 'http://mysite.dev:8080/' | |
// Proxy to Laravel backend | |
config.devServer = { | |
contentBase: 'public', | |
hot: true, | |
inline: true, | |
proxy: { | |
"**": "http://0.0.0.0:8000/", | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
config.plugins = [ | |
... config.plugins, | |
// ... other production plugins | |
// Dump manifest assetsByChunkName which is used by the webpack helper function | |
function onBuildComplete() { | |
this.plugin('done', function (stats) { | |
fs.writeFileSync( | |
path.join(__dirname, 'public', 'rev-manifest.json'), | |
JSON.stringify(stats.toJson().assetsByChunkName) | |
) | |
}) | |
} |
"**": "http://0.0.0.0:8000/"
finally I found this kind of magic
in Browsersync, it was proxy: env.APP_URL
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can also use ChunkManifestPlugin and then let require/webpack handle everything.