Method of using webpack encore in Laravel project

  • 2021-12-13 07:32:09
  • OfStack

Those who have read the blog I wrote before should know that I am straight laravel-mix There are several articles about it. When laravel-mix is mentioned, it is even more generous. However, just about a month ago, I decided to stop using it and switch to the webpack-encore camp.

As to why laravel-mix was abandoned, Mainly because its maintenance is worrying, Not only is the update pace slow, but many Issue have been pending for a long time. More importantly, the author seems to put a lot of bug completely in webpack5. Even if there are enthusiastic people PR, they are usually turned off, and then reply, "Brother dei, it is good to wait for webpack5 to come out. I have tried it before, so I guess you should fill in the pit and just wait for webpack5" (not the original words, but it is almost the same). But in the end, it was this Issue that made me make up my mind to seek an alternative. Looking through the source code, I found that the related functions depended on extract-text-webpack-plugin, and this package was declared abandoned as early as the release of webpack4 (now see that its official repository has been set to archived), but the author seems to have not used it at all mini-css-extract-plugin The meaning of.

As the saying goes, love is deep and responsibility is cut. After expressing disappointment with laravel-mix, I found out another package of webpack-encore of my own star for a long time. Although star has been around for a long time, I have never tried it before, probably because of my preference for laravel-mix. However, this time, I don't want to try it.

webpack-encore It is the official front-end integration construction tool of Symfony, which is also based on webpack, but its API is more friendly in design and better in documentation. Of course, the more critical point is that there are fewer pits... From the beginning of reading its documentation, it took only a few hours to migrate one project from laravel-mix to webpack-encore, and the period was quite smooth. The project I migrated is an Laravel project, so I will share it below. If I use it in the Laravel project, webpack-encore Substitution laravel-mix .

Install dependencies

First of all, of course, is the installation dependency

yarn add -D @symfony/webpack-encore

It should be noted that, webpack-encore There is no internal dependence like laravel-mix vue-tempplate-compiler Such packages, so if you use these in your own project, you need to install them manually in your own project.

Configuring webpack

Create a new one in the root directory of the project webpack.config.js File and configure it webpack-encore Features (in fact, it will eventually be a standard webpack configuration file), taking the most basic gameplay as an example.


const Encore = require('@symfony/webpack-encore')

Encore
// directory where compiled assets will be stored
 .setOutputPath('public/js/')
 // public path used by the web server to access the output path
 .setPublicPath('/js')
 // only needed for CDN's or sub-directory deploy
 //.setManifestKeyPrefix('build/')

 /*
  * ENTRY CONFIG
  *
  * Add 1 entry for each "page" of your app
  * (including one that's included on every page - e.g. "app")
  *
  * Each entry will result in one JavaScript file (e.g. app.js)
  * and one CSS file (e.g. app.css) if you JavaScript imports CSS.
  */.addEntry('app', './resources/js/app.js')

// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
 .enableSingleRuntimeChunk()

 .cleanupOutputBeforeBuild().enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
 .enableVersioning(Encore.isProduction())

 .enableVueLoader()
 .enableSassLoader(options => {
  options.implementation = require('sass')
 })

// fetch the config, then modify it!
const config = Encore.getWebpackConfig()

// export the final config
module.exports = config

Add php helper function

Laravel comes with an mix () function to reference resources compiled by mix, and syfony has such a function, which is more convenient. For this reason, you need to implement these two methods by yourself in the Laravel project. The following is what I rewrote with reference to the relevant source code in symfony, which may not be perfect logically, but they perform well after more than one month's use.


use Illuminate\Support\HtmlString;

/**
 * @param string $entryName
 * @return HtmlString
 */
function encore_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])) {
    return null;
  }

  $tags = array_map(function ($item) {
    return '<link rel="stylesheet" href="'.$item.'" rel="external nofollow" />';
  }, $jsonResult['entrypoints'][$entryName]['css']);

  return new HtmlString(implode('', $tags));
}

/**
 * @param string $entryName
 * @return HtmlString
 */
function encore_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])) {
    return null;
  }

  $tags = array_map(function ($item) {
    return '<script src="'.$item.'"></script>';
  }, $jsonResult['entrypoints'][$entryName]['js']);

  return new HtmlString(implode('', $tags));
}

Use mini-css-extract-plugin 0 And encore_entry_script_tags Reference to compiled front-end resources

Use the helper function added earlier to reference resources in the template, and you will find it more convenient than the mix () function that comes with Laravel. It only needs one function to automatically introduce vendor. js and app. js.


<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  <!-- CSRF Token -->
  <meta name="csrf-token" content="{{ csrf_token() }}">

  <title>{{ config('app.name') }}</title>

  <!-- app.css -->
  {{ encore_entry_link_tags('app') }}
</head>
<body>

  <div id="app"></div>

  {{ encore_entry_script_tags('app') }}
</body>
</html>

Modify the script in package. json (scripts)

Because the laravel project defaults package.json develop and other related scripts are all using laravel-mix, in order to facilitate daily development, now they have to be adjusted to use webpack-cocore . After adjustment, it is roughly as follows. You can also make other adjustments according to your actual application


"scripts": {
  "dev": "npm run development",
  "development": "cross-env NODE_ENV=development encore dev",
  "watch": "npm run development -- --watch",
  "watch-poll": "npm run watch -- --watch-poll",
  "hot": "encore dev-server --port=9001 --hot",
  "prod": "npm run production",
  "production": "cross-env NODE_ENV=production encore production"
},

Run the script and enjoy BUG

After completing the previous steps, execute yarn run hot on the terminal, and enter the domain name bound by the project (such as app. test) in the browser, so that you can experience convenient and efficient HMR development.

Postscript

Use webpack-encore It has been almost two months, and this period is generally quite smooth. Although there are small pits, there are no big pits. Go to github to mention issue, and the maintenance members are basically friendly and patient, and there will be a reply in a few hours. This attitude also makes me feel more at ease about it, and I believe it will get better and better. Although webpack-encore was designed as the default integration tool for Symfony, this does not prevent it from being powerful in Laravel.

Compared to laravel-mi API of encore and some default configurations are considered more scientifically and comprehensively. If you want to configure vue-loader or ts-loader, you only need to call the corresponding methods. In addition, to my surprise, they also took into account the default value of watchOptions. ignored, ignoring /node_modules/ by default, reducing CPU occupancy. Of course, more importantly, some functions that can't be used in mix4 because of bug are normal in encore, such as dynamic import.

Anyway, if you've found out laravel-mix If you have all kinds of shortcomings but suffer from no better choice, you might as well try webpack-encore I believe you will love it.

Summarize

The above is the site to introduce you in the Laravel project using webpack-encore method, this article gives you a very detailed introduction, with a set of reference value, the need for friends to refer to it!


Related articles: