illuminatech / override-build
允许使用补丁重新构建第三方库中的材料
Requires
- illuminate/console: ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0
- illuminate/filesystem: ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0
- illuminatech/array-factory: ^1.2.5
Requires (Dev)
- illuminate/config: *
- illuminate/container: *
- phpunit/phpunit: ^9.3 || ^10.5
README
Laravel Materials Build Override
此扩展允许使用补丁重新构建第三方库中的材料。
有关许可信息,请查看 LICENSE 文件。
安装
安装此扩展的首选方式是通过 composer。
运行
php composer.phar require --prefer-dist illuminatech/override-build
或添加
"illuminatech/override-build": "*"
到您的 composer.json 的 require 部分。
用法
此扩展允许使用补丁重新构建第三方库中的材料。在使用某些已包含编译JavaScript文件的扩展时可能很有用,您需要修改并重新编译这些文件。例如:第三方 CMS(如 Nova)的扩展。
我们可以以 froala/nova-froala-field 为例。此包包含集成到 VueJS 组件中的 JavaScript WYSIWYG 编辑器,它们一起编译成一个单独的 '*.js' 文件。如果您需要将 自定义插件 应用于编辑器,除非您使用自己的更改重新编译扩展,否则将无法实现。
在这种情况下,您可能会简单地调整 'vendor/froala/nova-froala-field' 目录内的源文件,并从那里运行 NPM 构建。然而,在 'vendor' 目录内进行的任何手动更改都可能导致您在未来遇到问题。以这种方式创建的补丁无法通过 VCS 跟踪,并且您将不得不在更新库时重新应用它。此外,对 "vendor" 目录中的文件所做的任何更改都可能导致 Composer 在 'install' 或 'update' 命令失败。
此包就是为了解决这个问题而创建的。它允许从不同路径下的特定源文件创建新的构建(编译)。此任务按照以下步骤执行
-
将不受 VCS 控制的源文件复制到新的 'build' 目录。
-
使用 'override' 目录中的文件(可能受 VCS 控制)追加/覆盖复制的文件。
-
对创建的文件应用预定义的补丁,如搜索替换或 JSON 修改。
-
在 'build' 目录文件上运行构建/编译。
注意! 实际上以这种方式重新构建第三方材料是一种黑客行为。除非您无法使用其他方法实现目标,否则请勿使用它。
应用程序配置
此扩展使用 illuminatech/array-factory 进行配置。在配置此扩展之前,请确保您熟悉 'array factory' 概念。配置存储在 'config/override-build.php' 文件中。
您可以使用以下控制台命令发布预定义的配置文件
php artisan vendor:publish --provider="Illuminatech\OverrideBuild\OverrideBuildServiceProvider" --tag=config
在配置文件中,您需要定义要重新构建的包列表。对于我们的 'Froala' 例子,配置可能如下所示
<?php return [ 'packages' => [ 'nova-froala-field' => [ 'srcPath' => base_path('vendor/froala/nova-froala-field'), // directory to get source files from 'srcFiles' => [ // probably you do not need to copy every vendor file, in this case you can list the needed ones here 'resources', '.babelrc', 'package.json', 'webpack.mix.js', ], 'buildPath' => storage_path('build-override/nova-froala-field'), // in this directory the new build will take place. 'overridePath' => app_path('Nova/Extensions/Froala'), // any file from this directory will be append to the source ones before build 'patches' => [ // list of patches to be applied to the source files. 'resources/js/field.js' => [ '__class' => Illuminatech\OverrideBuild\Patches\Wrap::class, 'template' => "{{INHERITED}}\n\nrequire('./custom-plugins');", ], ], 'buildCommand' => [ // shell commands to be executed for the build creation 'yarn install', 'yarn run prod', ], ], ], ];
每个包规范是 \Illuminatech\OverrideBuild\Builder
实例的 'array factory' 兼容配置。请参阅 \Illuminatech\OverrideBuild\Builder
类以获取有关特定选项的更多信息。
配置完成后,您可以使用 'override-build' artisan 命令运行重新构建。此命令接受配置中的包名称作为参数,指定哪个包应该被重新构建。例如
php artisan override-build nova-froala-field
注意!请记住,此扩展不会以使用新编译文件的方式重新配置构建的包。您必须手动调整您正在修改的扩展的配置。对于 'Nova Froala field' 的例子,您应该按照以下方式调整您的 \App\Providers\NovaServiceProvider
<?php namespace App\Providers; use Laravel\Nova\Nova; use Laravel\Nova\Events\ServingNova; use Laravel\Nova\NovaApplicationServiceProvider; class NovaServiceProvider extends NovaApplicationServiceProvider { public function boot() { parent::boot(); Nova::serving(function (ServingNova $event) { // override original JS for 'nova-froala-field' Nova::script('nova-froala-field', storage_path('build-override/nova-froala-field/dist/js/field.js')); }); } }
覆盖文件
您可能不需要对某个包进行任何修改就重新构建它。最简单的方法是使用 'override' 目录。它应该重复包含那些需要追加或替换的文件的源目录结构。在我们的 'Nova Froala field' 示例中,源目录具有以下结构
config/
database/
dist/
resources/
components/
DetailField.vue
FormField.vue
IndexField.vue
js/
FroalaAttachmentsAdapter.js
MediaConfigurator.js
PluginsLoader.js
TrixAttachmentsAdapter.js
field.js
routes/
src/
.babelrc
package.json
它的覆盖目录结构可能如下所示
resources/
js/
field.js
custom-plugins.js
它的应用将替换 'resources/js/field.js' 文件,并追加 'resources/js/custom-plugins.js'。
原始的 'resources/js/field.js' 文件内容如下
require('froala-editor/js/froala_editor.pkgd.min'); require('froala-editor/js/plugins.pkgd.min.js'); import VueFroala from 'vue-froala-wysiwyg'; Nova.booting(Vue => { Vue.use(VueFroala); Vue.component('index-nova-froala-field', require('./components/IndexField')); Vue.component('detail-nova-froala-field', require('./components/DetailField')); Vue.component('form-nova-froala-field', require('./components/FormField')); });
覆盖可能包含额外的代码,添加在 'resources/js/custom-plugins.js' 文件中定义的自定义编辑器插件
require('froala-editor/js/froala_editor.pkgd.min'); require('froala-editor/js/plugins.pkgd.min.js'); require('./custom-plugins'); // add custom plugins to the build import VueFroala from 'vue-froala-wysiwyg'; Nova.booting(Vue => { Vue.use(VueFroala); Vue.component('index-nova-froala-field', require('./components/IndexField')); Vue.component('detail-nova-froala-field', require('./components/DetailField')); Vue.component('form-nova-froala-field', require('./components/FormField')); });
修补文件
虽然完全覆盖源文件是最简单的方式应用您的修改,但它有一些显著的缺点。您需要将所有原始文件内容复制到覆盖中,然后进行修改,即使只是更改一行代码。在源库升级的情况下,它可能会更改您覆盖的文件,导致构建结束时出现错误。为了使您的更改更加持久,已创建了 \Illuminatech\OverrideBuild\Builder::$patches
。每个补丁都是一个匹配 \Illuminatech\OverrideBuild\PatchContract
的 PHP 对象,它修改文件内容。以下是一些预定义的补丁
-
\Illuminatech\OverrideBuild\Patches\Replace
- 替换一组字符串。 -
\Illuminatech\OverrideBuild\Patches\Wrap
- 将原始内容包装到指定的字符串中,允许追加/前置额外的行。 -
\Illuminatech\OverrideBuild\Patches\Json
- 允许修改 JSON 结构。
请参阅特定的补丁类以获取更多详细信息。
对于我们的 'Nova Froala field' 示例,我们可以简单地修补 'resources/js/field.js',添加一行额外的代码 require('./custom-plugins');
,而不是完全重写它。
<?php return [ 'packages' => [ 'nova-froala-field' => [ // ... 'patches' => [ 'resources/js/field.js' => [ // wrap the original file content, appending `require('./custom-plugins');` to the end of the file '__class' => Illuminatech\OverrideBuild\Patches\Wrap::class, 'template' => "{{INHERITED}}\n\nrequire('./custom-plugins');", ], ], // ... ], ], ];
构建优化
为了加快构建过程,'override-build' 在创建新的构建之前会检查包构建是否已存在。如果构建存在,并且其文件修改日期晚于 'source' 和 'override' 目录中的文件修改日期,则不会启动新的构建。您可以通过在命令调用中使用 --force
标志强制重新创建构建。例如
php artisan override-build nova-froala-field --force
清理文件
在构建过程中,可能会生成一些您可能不想保留的辅助文件。例如,在我们的 'Nova Froala field' 示例中构建时,会创建包含所有 NPM 依赖项的 'node_modules' 目录。为了简化项目结构并节省磁盘空间,您可以设置 \Illuminatech\OverrideBuild\Builder::$cleanupFiles
,列出构建完成后应删除的文件和目录。例如
<?php return [ 'packages' => [ 'nova-froala-field' => [ // ... 'cleanupFiles' => [ 'node_modules', 'yarn.lock', ], ], ], ];