Angular 5与Laravel集成:如何获取ng build生成的文件名?
解决Angular 5构建后无法获取哈希资源文件名用于Laravel Blade的问题
我之前在Laravel + Angular 5的项目里也碰到过一模一样的困扰——默认的ng build不会生成能直接读取的manifest文件,没法轻松拿到带哈希的资源文件名给Blade模板用,总不能每次都手动改或者读index.html。下面分享几个我亲测有效的方案:
方案一:自定义Webpack配置生成Manifest文件
Angular 5可以通过自定义Webpack配置来集成webpack-manifest-plugin,让构建时自动生成资源映射的manifest.json:
- 先安装依赖:
npm install @angular-builders/custom-webpack webpack-manifest-plugin --save-dev
- 在项目根目录创建
webpack.config.js,添加Manifest插件配置:
const ManifestPlugin = require('webpack-manifest-plugin'); module.exports = { plugins: [ new ManifestPlugin({ fileName: 'manifest.json', publicPath: '/dist/', // 这里要对应你Angular打包后的资源访问路径 generate: (seed, files) => { // 只提取我们需要的js、css文件,过滤掉其他资源 const manifest = files.reduce((acc, file) => { if (file.name.match(/main\..*\.js|styles\..*\.css/)) { const key = file.name.split('.')[0]; // 用main、styles作为键名 acc[key] = file.path; } return acc; }, seed); return manifest; } }) ] };
- 修改
angular.json(旧版本可能是.angular-cli.json)的构建配置,替换默认builder为自定义webpack builder:
"architect": { "build": { "builder": "@angular-builders/custom-webpack:browser", "options": { "customWebpackConfig": { "path": "./webpack.config.js" }, "outputPath": "public/dist", // 打包到Laravel的public目录下 "outputHashing": "all", // 确保生成带哈希的文件名 // 其他原有配置... } } }
- 运行
ng build --prod后,public/dist目录下会生成manifest.json,内容大概是:
{ "main": "/dist/main.abc123.js", "styles": "/dist/styles.def456.css" }
- 在Laravel里,你可以在控制器或者视图composer里读取这个json文件,把资源路径传递给Blade模板:
$manifest = json_decode(file_get_contents(public_path('dist/manifest.json')), true); return view('app')->with('angularAssets', $manifest);
然后在Blade里直接使用:
<script src="{{ $angularAssets['main'] }}"></script> <link rel="stylesheet" href="{{ $angularAssets['styles'] }}">
方案二:Post-Build脚本手动生成资源映射
如果不想折腾Webpack配置,可以写个简单的Node脚本,在构建完成后自动扫描dist目录,生成资源映射文件:
- 在项目根目录创建
generate-manifest.js:
const fs = require('fs'); const path = require('path'); const distDir = path.join(__dirname, 'public/dist'); const manifest = {}; // 读取dist目录下的文件 fs.readdirSync(distDir).forEach(file => { if (file.startsWith('main.') && file.endsWith('.js')) { manifest.main = `/dist/${file}`; } else if (file.startsWith('styles.') && file.endsWith('.css')) { manifest.styles = `/dist/${file}`; } }); // 写入manifest.json fs.writeFileSync(path.join(distDir, 'manifest.json'), JSON.stringify(manifest, null, 2)); console.log('Manifest generated successfully!');
- 修改
package.json的scripts,把构建和脚本执行连起来:
"scripts": { "build:prod": "ng build --prod && node generate-manifest.js" }
- 运行
npm run build:prod就会自动生成manifest.json,后续用法和方案一一致。
方案三:Laravel端直接读取资源文件
如果前端不想做任何修改,也可以在Laravel里用文件匹配的方式直接获取哈希后的文件名:
比如在Laravel的服务提供者里添加视图composer:
use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\File; public function boot() { View::composer('app', function ($view) { // 匹配main开头的js文件 $mainJs = File::glob(public_path('dist/main.*.js'))[0] ?? ''; // 匹配styles开头的css文件 $stylesCss = File::glob(public_path('dist/styles.*.css'))[0] ?? ''; $view->with([ 'mainJs' => $mainJs ? str_replace(public_path(), '', $mainJs) : '', 'stylesCss' => $stylesCss ? str_replace(public_path(), '', $stylesCss) : '' ]); }); }
然后在Blade里使用:
@if($mainJs) <script src="{{ $mainJs }}"></script> @endif @if($stylesCss) <link rel="stylesheet" href="{{ $stylesCss }}"> @endif
小提示
确保Angular的outputHashing设置正确,在angular.json里把outputHashing设为"all",这样所有打包后的资源都会带哈希值,方便缓存更新。
内容的提问来源于stack exchange,提问作者Sallu
相关产品推荐
相关产品推荐

