XF 2.2 Template Syntax JS tag - How does versioning work?

CStrategies

Member
I tried adding a version number to the file location in the JS tag:

Code:
<xf:js prod="myscript/myscript_min.js?v=1.1" dev="myscript/myscript.js?v=1.1" />

However, this rendered as:

Code:
<script src="/js/myscript/myscript_min.js?v=1.1&amp;_v=04a5b62b"></script>

I noticed other scripts on the page seem to have this automatically applied version number 04a5b62b. I want to ensure that the user's browser downloads a new copy of the script when I update my addon, but I don't understand how the versioning is being decided here.
 
I want to ensure that the user's browser downloads a new copy of the script when I update my addon, but I don't understand how the versioning is being decided here.
You don't have to do anything manually to achieve this, XenForo already does take care of cache invalidation (by using a Cache-Buster hash _v=04a5b62b which is automatically appended to the URL and changed when JS files change (precisely: when the hidden JS timestamp option is modified).

Just reference your JS as <xf:js src="myvendor/mypackage/myscript.js" addon="MyVendor/MyAddon" min="1" /> , keep the file within the _files folder of your Add-on directory and have smth. like

Code:
    "additional_files": [
        "js/myvendor/mypackage/myscript.js",
    ],
    "minify": [
        "js/myvendor/mypackage/myscript.js"
    ]

in your build.json

 
You don't have to do anything manually to achieve this, XenForo already does take care of cache invalidation (by using a Cache-Buster hash _v=04a5b62b which is automatically appended to the URL and changed when JS files change (precisely: when the hidden JS timestamp option is modified).

Just reference your JS as <xf:js src="myvendor/mypackage/myscript.js" addon="MyVendor/MyAddon" min="1" /> , keep the file within the _files folder of your Add-on directory and have smth. like

Code:
    "additional_files": [
        "js/myvendor/mypackage/myscript.js",
    ],
    "minify": [
        "js/myvendor/mypackage/myscript.js"
    ]

in your build.json


Some things I'm encountering trying this method (and ultimately failing):

The minifier seems to be broken. I kept getting the Unexpected error while minifying JS: Empty result provided by the compiler error, and others seem to have the same problem with no solution.

The "addon" attribute seems to only be for development: https://xenforo.com/docs/dev/template-syntax/#js-tag

Did not realize you could not just drop the .js files into _files. Wouldn't work until I made folders inside _files i.e. _files/js/myvendor/mypackage/myscript.js.

Finally got it to build, and nothing was copied to the root js folder. No matter what URL I use for the src attribute, it doesn't find the file.

I gave up on this method and tried putting the .js files in a js folder in my addon folder, building the addon, and using the URL myvendor/myaddon/myscript.js but that didn't work.

Packaging js into my addon is still a mystery to me unfortunately. The only way that works for me is manually copying js to the root js folder, which only works because I have access to the production server.
 
Last edited:
Is this something where the build process itself doesn't copy the files, and the addon has to be installed or updated through the ACP for XF to copy its files to the js folder?
 
The minifier seems to be broken. I kept getting the Unexpected error while minifying JS: Empty result provided by the compiler error, and others seem to have the same problem with no solution.
You can download the Closure Compiler binary manually and set the path in config.php to minify locally instead of relying on the API:

The "addon" attribute seems to only be for development: https://xenforo.com/docs/dev/template-syntax/#js-tag
It is for serving the file from the add-on directory when development mode is enabled, yes. It doesn't need to be removed for production or anything though, it is simply ignored.

Did not realize you could not just drop the .js files into _files. Wouldn't work until I made folders inside _files i.e. _files/js/myvendor/mypackage/myscript.js.
Generally _files should mirror the structure you want the files copied to in the XF root directory.

Finally got it to build, and nothing was copied to the root js folder. No matter what URL I use for the src attribute, it doesn't find the file.
Did you set up build.json per Kirby's instructions?

Is this something where the build process itself doesn't copy the files, and the addon has to be installed or updated through the ACP for XF to copy its files to the js folder?
The build process builds them into the zip file, but does not copy them to your local installation. That's what the addon attribute is for -- it will serve them from the add-on folder.
 
You can download the Closure Compiler binary manually and set the path in config.php to minify locally instead of relying on the API:


It is for serving the file from the add-on directory when development mode is enabled, yes. It doesn't need to be removed for production or anything though, it is simply ignored.


Generally _files should mirror the structure you want the files copied to in the XF root directory.


Did you set up build.json per Kirby's instructions?


The build process builds them into the zip file, but does not copy them to your local installation. That's what the addon attribute is for -- it will serve them from the add-on folder.

Thank you Jeremy. Could you clarify a couple things for me?

For context, we have a separate development environment for building addons, and when the changes are complete and the addon is built, it is pushed to the production server through git.

I set up my build.json like so, and tested updating the addon manually on the dev server in development mode, and it correctly copied the js files to the root js folder:
Code:
{
    "additional_files": [
        "js/MyVendor/MyAddon"
    ],
    "exec": [
        "echo '{title} version {version_string} ({version_id}) has been built successfully!'"
    ]    
}

In my addon folder, the file structure is:

MyVendor -> MyAddon -> _files -> js -> MyVendor -> MyAddon -> myscript.min.js

In my template, the js tag is set up as:

<xf:js prod="MyVendor/MyAddon/myscript.min.js" dev="MyVendor/MyAddon/myscript.min.js" addon="MyVendor/MyAddon" />

(I am minifying the script locally before upload)

What I had hoped, from your description, is that in our development environment with development mode on, this js tag would serve the copy of myscript.min.js that is in the addon's _files folder. However, even with the dev and addon attributes set, it is still serving from the root js folder. I confirmed this by adding a console log statement to the version that's in the addon folder.

My other concern is whether pushing changes through git (versus manual upgrade through the ACP) will interfere with the automatic appending of the cache-buster version number. If that is the case, I may have to go back to the original plan of manually inserting a version number into the js tag.
 
<xf:js prod="MyVendor/MyAddon/myscript.min.js" dev="MyVendor/MyAddon/myscript.min.js" addon="MyVendor/MyAddon" />
This makes no sense at all as prod and dev are identical. Using prod and dev is only required if you want to use a rollup file for production but multiple / different files for dev.

If you have only one file it should be
<xf:js src="MyVendor/MyAddon/myscript.js" addon="MyVendor/MyAddon" min="1" />

In order to use the file from _files you must enable this via config.php (I assumed you had already done this):

PHP:
$config['development']['fullJs'] = true;
 
Last edited:
This makes no sense at all as prod and dev are identical. Using prod and dev is only required if you want to use a rollup file for production but multiple / different files for dev.

If you have only one file it should be
<xf:js src="MyVendor/MyAddon/myscript.js" addon="MyVendor/MyAddon" min="1" />

In order to use the file from _files you must enable this via config.php (I assumed you had already done this):

PHP:
$config['development']['fullJs'] = true;
Ok I understand the context now after re-reading https://xenforo.com/docs/xf2/config/#development-mode

Thanks.
 
My other concern is whether pushing changes through git (versus manual upgrade through the ACP)
Updating a production website straight from VCS IMHO doesn't work well due to things you've already noticed (JS files not in /js, JS files not minimized, hashes.json missing, Add-on data not imported if not running in development mode due to _data missing).

I'd therefore take a different approach:
Develop > Push to VCS > CI > Build > Store build artifact (eg. ZIP) > Tag / Release > CD > Deploy

The last step inolves transfering the ZIP to production instances, unpack there and run xf-addon:upgrade

(XenForo 2.3 will simplify this by directly allowing to install / upgrade an Add-on from a ZIP via cli)
 
Last edited:
Top Bottom