Yii2: Use mutex when publishing assets

Created on 22 Apr 2014  路  5Comments  路  Source: yiisoft/yii2

There's a potential problem with the current way of asset publishing, especially when a converter is used. On a high load website, if there are many requests coming in on a "cold" system without any assets published, this may cause a large number of conversion processes to get startet. The longer the conversion takes, the more processes and the higher the load on the server. This can make the server unresponsive for quite some time.

I therefore suggest to add a mutex lock to the asset publisher, so that each asset is really only published once.

BC breaking enhancement

Most helpful comment

Adding a lock here may improve situation, but it feels similar to the "Pjax situation": We'll never find a 100% reliable solution that works in any thinkable scenario.

Personally I find publishing assets at runtime was a nice idea at the time. But to be honest I don't use in production anymore (except for low traffic sites). Instead I have my custom build chain for bundling assets into a public directory that is part of the repo. It requires some manual configuration but after that everything runs rock solid. No hidden automatism, which I like.

So if it where me: Good bye assetManager, welcome "asset" cli command (or similar)!

All 5 comments

this issue is 2 years old and @mikehaertl demonstrates a risk. How do we currently look at this? Should we add a mutex lock? @mikehaertl? @rob006? @kidol?

Adding a lock here may improve situation, but it feels similar to the "Pjax situation": We'll never find a 100% reliable solution that works in any thinkable scenario.

Personally I find publishing assets at runtime was a nice idea at the time. But to be honest I don't use in production anymore (except for low traffic sites). Instead I have my custom build chain for bundling assets into a public directory that is part of the repo. It requires some manual configuration but after that everything runs rock solid. No hidden automatism, which I like.

So if it where me: Good bye assetManager, welcome "asset" cli command (or similar)!

thanks for your comment. Can you elaborate on how you are publishing all of your assets during your deploy?

Can you elaborate on how you are publishing all of your assets during your deploy?

My setup is very specific, like making heavy use of docker e.g. to build the assets. So not sure, how helpful any of this is for a potential ./yii asset command. But FWIW:

I don't publish during deploy. I publish before committing (i.e. there's a "build" step). The setup is just a bunch of cli commands in the scripts section of my package.json for npm. Plain, simple and easy to reason about. I usually also only need a couple of Yii's assets, so I add them manually there.

Here's a snippet:

 "browserify": {
    "transform": [
      "browserify-shim",
      ["babelify", {
        "presets": "es2015"
      }]
    ]
  },
  "browser" : {
    "yii": "../vendor/yiisoft/yii2/assets/yii.js",
    "yii.validation": "../vendor/yiisoft/yii2/assets/yii.validation.js",
    "yii.activeForm": "../vendor/yiisoft/yii2/assets/yii.activeForm.js"
  },
  "browserify-shim": {
    "jquery": "global:jQuery"
  },
  "scripts": {
    "build": "npm run build:js && npm run build:css",
    "build:js": "npm run js:clean && npm run js:browserify && npm run js:hash && npm run js:reference && npm run js:reference_map && npm run js:deploy",
    "build:css": "npm run css:clean && npm run css:sass && npm run css:autoprefix && npm run css:hash && npm run css:reference && npm run css:deploy",

    "js:clean": "rm -f ../web/js/main_*.js && rm -f ../web/js/main*.js.map",
    "js:browserify": "browserify -d -p [minifyify --map main.js.map --output main.js.map] scripts/main.js > main.js",
    "js:hash": "hashmark -s -l 8 main.js 'main_{hash}.js' && hashmark -s -l 8 main.js.map 'main_{hash}.js.map' && rm main.js*",
    "js:reference": "sed -i \"s/main_.*\\.js/$(basename main_*.js)/\" ../views/layouts/main.php",
    "js:reference_map": "sed -i \"s/main\\.js\\.map/$(basename main_*.js.map)/\" ./main_*.js",
    "js:deploy": "mv main_* ../web/js/",

and in my scripts/main.js:

// Yii js
import 'yii';
import 'yii.validation';
import 'yii.activeForm';

What this does:

  • Transpile my ES2015 files to a single, browser compatible main.js
  • Create a hash from the content and use it in the filename like main_c03ef3aa.js
  • Auto-update the reference in views/layouts/main.php to point to the newly built js file

alright. Thanks for sharing. To conclude. This issue will not likely cause issues for small/medium websites. For those large websites, this problem will likely be tackled already by:

  • Yiis asset bundling mechanism
  • the of linked assets
  • or custom implementations like the one of @mikehaertl
Was this page helpful?
0 / 5 - 0 ratings

Related issues

MUTOgen picture MUTOgen  路  3Comments

AstRonin picture AstRonin  路  3Comments

indicalabs picture indicalabs  路  3Comments

jpodpro picture jpodpro  路  3Comments

Locustv2 picture Locustv2  路  3Comments