在 Laravel 项目中使用 webpack-encore的方法
看过我之前写过的博客的应该知道我一直是laravel-mix的死忠粉,有好几篇文章都是关于它的。每每提到laravel-mix时更是不吝溢美之词。然而就在大概一个月前,我却决定不再使用它,而转投webpack-encore阵营。
至于为什么放弃laravel-mix,主要是因为它的维护状况堪忧,不仅更新节奏缓慢,许多Issue久悬未决,更重要的是,作者似乎将很多bug完全寄希望于webpack5,哪怕有热心人士PR了,也通常被关掉,然后回复说“兄dei,这个坑等webpack5出来就好了,我之前试过没弄好,估计你这也填好坑,干脆安分点儿等webpack5吧”(不是原话,但差不多是这意思)。但最终让我下定决心寻求替代方案的,则是这个 Issue,细翻源码,发现相关功能依赖的还是extract-text-webpack-plugin,而这个包,早在webpack4发布不久就被宣布废弃了(现在去看它的官方仓库已经被设置为archived),而作者似乎完全没有使用mini-css-extract-plugin的意思。
正所谓爱之深,责之切,在对laravel-mix表示失望之后,我翻出了自己star多时的另一包webpack-encore,虽说很早就star了,但之前却没试用过它,可能也是因为对于laravel-mix的偏爱,然而这次,不试便罢,试完之后大有相见恨晚之意。
webpack-encore是Symfony官方的前端集成构建工具,同样是基于webpack,但它的API设计得更为友好,而且文档更完善,当然更关键的一点是,坑更少啊……从开始读它的文档,倒把手里一个项目从laravel-mix迁移到webpack-encore,只用了几个小时,并且期间相当顺利。而我迁移的这个项目,是一个Laravel项目,所以下面就分享下,如果在Laravel项目中使用webpack-encore替代laravel-mix。
安装依赖
首先当然是安装依赖
yarnadd-D@symfony/webpack-encore
需要注意的是,webpack-encore没有像laravel-mix那样在自己内部依赖vue-tempplate-compiler之类的包,所以如果自己项目里用动了这些,需要自己在项目里手动安装好。
配置webpack
在项目根目录下新建一个webpack.config.js文件并在其中配置webpack-encore功能(实际上它最终也是一个标准的webpack配置文件),以最基本的玩法为例。
constEncore=require('@symfony/webpack-encore') Encore //directorywherecompiledassetswillbestored .setOutputPath('public/js/') //publicpathusedbythewebservertoaccesstheoutputpath .setPublicPath('/js') //onlyneededforCDN'sorsub-directorydeploy //.setManifestKeyPrefix('build/') /* *ENTRYCONFIG * *Add1entryforeach"page"ofyourapp *(includingonethat'sincludedoneverypage-e.g."app") * *EachentrywillresultinoneJavaScriptfile(e.g.app.js) *andoneCSSfile(e.g.app.css)ifyouJavaScriptimportsCSS. */.addEntry('app','./resources/js/app.js') //willrequireanextrascripttagforruntime.js //but,youprobablywantthis,unlessyou'rebuildingasingle-pageapp .enableSingleRuntimeChunk() .cleanupOutputBeforeBuild().enableSourceMaps(!Encore.isProduction()) //enableshashedfilenames(e.g.app.abc123.css) .enableVersioning(Encore.isProduction()) .enableVueLoader() .enableSassLoader(options=>{ options.implementation=require('sass') }) //fetchtheconfig,thenmodifyit! constconfig=Encore.getWebpackConfig() //exportthefinalconfig module.exports=config
新增phphelper函数
Laravel自带了一个mix()函数用于引用mix编译的资源,与之类似,syfony也有这样的函数,而且更为方便。为此你需要在Laravel项目中自行实现这两方法,下面是我参考symfony里相关源码改写的,可能逻辑上并不算完善,但以自己一个多月的使用情况来看,它们表现良好。
useIlluminate\Support\HtmlString; /** *@paramstring$entryName *@returnHtmlString */ functionencore_entry_link_tags(string$entryName):HtmlString { $entryPointsFile=public_path('js/entrypoints.json'); $jsonResult=json_decode(file_get_contents($entryPointsFile),true); if(!array_key_exists('css',$jsonResult['entrypoints'][$entryName])){ returnnull; } $tags=array_map(function($item){ return''; },$jsonResult['entrypoints'][$entryName]['css']); returnnewHtmlString(implode('',$tags)); } /** *@paramstring$entryName *@returnHtmlString */ functionencore_entry_script_tags(string$entryName):HtmlString { $entryPointsFile=public_path('js/entrypoints.json'); $jsonResult=json_decode(file_get_contents($entryPointsFile),true); if(!array_key_exists('js',$jsonResult['entrypoints'][$entryName])){ returnnull; } $tags=array_map(function($item){ return' '; },$jsonResult['entrypoints'][$entryName]['js']); returnnewHtmlString(implode('',$tags)); }
使用 encore_entry_link_tags和 encore_entry_script_tags引用编译的前端资源
在模板里使用前面添加的helper函数引用资源,你会发现它比Laravel自带的mix()函数更方便,只需要一个函数,就可以自动引入vendor.js和app.js了。
getLocale()}}"> {{config('app.name')}} {{encore_entry_link_tags('app')}}