WordPress.org

Make WordPress Core

Opened 3 years ago

Last modified 7 weeks ago

#24152 reopened feature request

Use JSON as alternative to headers

Reported by: ryanve Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Themes Keywords: close
Focuses: Cc:

Description

Themes are required to include style.css for its header info. Plugins are required to contain header info in their main file. It makes more sense to store package info in JSON. A filename like theme.json or plugin.json (or an all-encompassing wordpress.json) seems viable. When present, the JSON file would be favored over the headers. This would make it possible to have a theme without a style.css file.

Change History (27)

#1 @ryanve
3 years ago

  • Type changed from defect (bug) to feature request

#2 @toscho
3 years ago

  • Cc info@… added

Oh, yes please!

#3 @TJNowell
3 years ago

  • Cc tom@… added

#4 @johnbillion
3 years ago

  • Cc johnbillion added

#5 @SergeyBiryukov
3 years ago

  • Component changed from General to Themes

#6 @nacin
3 years ago

  • Keywords close added

While this means you don't need a style.css file for a theme, you'll still need a .json file. Considering you don't actually need to use style.css for, well, CSS, this isn't much of a benefit. If anything, it means people will need to look in two places, not one. And given that all plugins do need a file, this will mean that plugins now need a minimum of two files. (Many plugins are very simple single-file plugins that can go into wp-content/plugins directly, and this is common for custom managed sites.)

While JSON files are both machine-readable and human-readable, they aren't necessarily human-editable. You need to understand syntax and such, and there are some gotchas like trailing commas and when to quote that can be confusing. I think this would be a nice thing to keep in our back pocket in case the world of dependencies, testing, and such force something more powerful than the existing headers. But the current headers are a very integral part of WordPress and are one of those things that make things so simple to so many.

Cool idea, but suggesting we close this as maybelater.

#7 @rmccue
3 years ago

Oh please no. I love JSON as an interchange format between machines, but as configuration files, they're just insane. Agreed with nacin, +1 on close.

#8 @markoheijnen
3 years ago

+1 for close it too. For dependencies it can be a JSON file but then use a file only for that.

#9 @nacin
3 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from new to closed

#10 @travisnorthcutt
3 years ago

this will mean that plugins now need a minimum of two files.

Not to nitpick (ok, to nitpick), doesn't the proposed functionality (When present, the JSON file would be favored over the headers.) suggest that a json file isn't strictly required, and the existing method of using headers would still work just fine?

#11 @TJNowell
3 years ago

Keeping in mind that themes already need 2 files as a minimum, index.php and style.css, and that the primary argument against this is a situation that we already have in plugins, namely that we have to define our plugin in the header, and readme.txt

#12 @zamoose
3 years ago

@TJNowell:
Extra nitpicking: if it's a child theme, you don't even need an index.php.

#13 @ocean90
21 months ago

#29363 was marked as a duplicate.

#14 @Alaa Rihan
21 months ago

in drupal they will use yaml to store themes and modules info in drupal -v8..

why we don't use php like "[Theme name].info.php" or xml like "[Theme name].xml"?

#15 @ocean90
16 months ago

#30974 was marked as a duplicate.

#16 @retlehs
16 months ago

Time to revisit? The non-standard file headers specification is 17 different things, when it could be reduced to just "use valid JSON"

For backwards compat, the feature could work along the lines of: if less than 4.x, use get_file_data, if newer, use json_decode

#17 follow-up: @swalkinshaw
16 months ago

  • Resolution wontfix deleted
  • Status changed from closed to reopened

I'm re-opening this because I believe it should be open to discussion again and I'm going to address the reasons against this in the first place.

Summary

There should be a single consistent file where metadata for plugins and themes is contained. Theme metadata does not belong in the comments of a stylesheet. While it's slightly better being in a plugin's PHP file, creating a separate file would allow for uniformity and consistency. Replacing a custom non-standard specification that uses slow and error prone regular expressions with a well-known, performant, and mature standard like JSON is a big win. This metadata file would also allow more flexibility in the future.

Benefits

  • Performance: I haven't seen this mentioned before, but the current file headers parsing is quite slow due to regular expression usage. I made a very simple micro-benchmark to parse the exact same headers with the current WP method and also with json_decode and parse_ini_file. This benchmark just does 10000 iterations of the parsing.

Results:

  • get_file_data: 1.98s
  • json_decode: 218ms
  • parse_ini_file: 482ms

Obviously the usual disclaimers about benchmarks apply here. But that's almost 10x faster.

Note: I included parse_ini_file here in case the issue is really over JSON itself and not strictly a separate metadata file.

  • Dependencies: As mentioned above, a metadata file would allow for more flexibility for features like dependencies. Without it, a feature like that will probably never happen.
  • Uniformity: since JSON has a spec and built-in parsers in basically every language, it doesn't necessarily matter how you format whitespace for example. But with the current file headers, there's no uniformity and it can cause problems. Here's an example from the bug above:
 Original Theme Name
	Original Theme Name
        Theme Name
      Theme Name
    Theme Name
  Theme Name
 *   Theme Name
 * Theme Name
 *Theme Name
 Theme Name
/* Theme Name
/*	Theme Name
/*Theme Name
* Theme Name
/*Theme Name
		Theme Name
	Theme Name
Theme Name

Rebuttals

While this means you don't need a style.css file for a theme, you'll still need a .json file. Considering you don't actually need to use style.css for, well, CSS, this isn't much of a benefit. If anything, it means people will need to look in two places, not one.

Right now for a theme, you need to look in the style.css file to find the theme metadata. While this may be obvious to people familiar with WordPress, it doesn't actually make logic sense. Why would a theme's metadata be in comments in a stylesheet? It's an arbitrary choice. Why not a scripts.js file? Or the index.php file? A separate file for metadata is more common sense and logical since it's used across all software.

It would also make things consistent between plugins and themes. Right now you need to look in a stylesheet for one and a PHP for another. This is logical at all.

While JSON files are both machine-readable and human-readable, they aren't necessarily human-editable. You need to understand syntax and such, and there are some gotchas like trailing commas and when to quote that can be confusing.

The [File Header Specification](http://codex.wordpress.org/File_Header) is completely non-standard and is just a list of 17 things. There's no formal spec and frankly nothing really like it. While JSON may be harder to edit than the current headers (which is debatable), as it's a well known standard with a formal specification and tools to edit, validate, and parse it.

I also think JSON has gotten even more used since nacin's comment 21 months ago thanks to Composer in the PHP world and JavaScript.

Oh please no. I love JSON as an interchange format between machines, but as configuration files, they're just insane.

See above. Tons of popular tools use JSON as a configuration format including in the PHP world.

+1 for close it too. For dependencies it can be a JSON file but then use a file only for that.

Why would you have a separate file just for dependencies and not move the metadata to there as well? This goes completely against what many popular tools are doing now. See npm's package.json and Composer's composer.json.

Keeping in mind that themes already need 2 files as a minimum, index.php and style.css, and that the primary argument against this is a situation that we already have in plugins, namely that we have to define our plugin in the header, and readme.txt

This is a great point which a separate metadata file also solves. There should be a common file for plugins and themes which would replace file headers and deprecate the need for a readme.txt file.

Last edited 16 months ago by swalkinshaw (previous) (diff)

#18 follow-up: @TJNowell
16 months ago

I would rather we allowed the use of package.json or composer.json rather than a new file and specification. composer.json already has precedents for defining a wordpress theme, and provisions for any additional data not already covered. It's a spec already in use by various projects and the PHP world at large, with a well tested toolchain.

If we added another json file, we could have the same information in 3 files if someone who uses Composer decided to also use grunt etc, which is an unnecessary level of redundancy to keep track of.

#19 in reply to: ↑ 18 @swalkinshaw
16 months ago

Replying to TJNowell:

I would rather we allowed the use of package.json or composer.json rather than a new file and specification. composer.json already has precedents for defining a wordpress theme, and provisions for any additional data not already covered. It's a spec already in use by various projects and the PHP world at large, with a well tested toolchain.

If we added another json file, we could have the same information in 3 files if someone who uses Composer decided to also use grunt etc, which is an unnecessary level of redundancy to keep track of.

That's a good idea and fine with me. I'm not really arguing for a "new file" specifically. More so just to get rid of the file headers and move them into their own file (whatever that may be).

edit: if anything, composer.json makes sense over package.json for obvious reasons. I mostly didn't get into Composer in my reply because I don't want the discussion to get caught up into another debate over it. This is really just about a better file headers replacement.

Last edited 16 months ago by swalkinshaw (previous) (diff)

#20 @SergeyBiryukov
15 months ago

  • Milestone set to Awaiting Review

This ticket was mentioned in Slack in #meta by obenland. View the logs.


15 months ago

#22 @francogilio
8 months ago

+1

I like this idea. I personally agree with all the pros mentioned above, especially "This is really just about a better file headers replacement".

Not sure about using package.json or composer.json. Maybe have a wordpress.json, and fallback to the other 2 if not present.

#23 @jamesgol
7 months ago

I was going to open a ticket like this and found this while searching. In my tests the JSON method is significantly faster and provides further capabilities (namely including values in an array as part of an arbitrary header which would be required for an idea I am toying around with).

There is already a readme.txt validator on wordpress.org, there could easily be a json validator as well as many other ways to automatically generate the required files.

It would be trivial to keep this backwards compatible, as if the required json file doesn't exist it falls back to the old method (unless disabled via a defined constant or past a version if ever deprecated).

#24 in reply to: ↑ 17 ; follow-up: @nacin
7 months ago

Replying to swalkinshaw:

  • Performance: I haven't seen this mentioned before, but the current file headers parsing is quite slow due to regular expression usage. I made a very simple micro-benchmark to parse the exact same headers with the current WP method and also with json_decode and parse_ini_file. This benchmark just does 10000 iterations of the parsing.

Results:

  • get_file_data: 1.98s
  • json_decode: 218ms
  • parse_ini_file: 482ms

Are these numbers based on the average or the sum of 10000 iterations?

I'd identify one problem with these benchmarks. get_file_data() and parse_ini_file() both hit the filesystem. json_decode() does not. If you didn't account for that, well, that I/O hit is pretty significant. If you did account for it, then I'd suggest that benchmarking this at high iterations isn't all that useful, since it'd only ever be run a few times on a pageload anyway.

  • Dependencies: As mentioned above, a metadata file would allow for more flexibility for features like dependencies. Without it, a feature like that will probably never happen.

I think this is a cart before the horse. I am not sure the form in which dependencies will happen, but if it's determined we need something like this, then we'd do it. But not having this at the moment is not blocking any work on dependencies.

Those tickets are both five years old, not long after we consolidated all of this logic into a single get_file_data() function, and I've seen nothing to suggest we still have edge cases here.

  • Uniformity: since JSON has a spec and built-in parsers in basically every language, it doesn't necessarily matter how you format whitespace for example. But with the current file headers, there's no uniformity and it can cause problems. Here's an example from the bug above:

I don't really have a problem with this. Only WP needs to do this parsing.

As I indicated originally, I totally understand the desire and the use case. I just don't believe it is a complexity we have any need to introduce right now, regardless of format (json v yaml).

#25 in reply to: ↑ 24 @swalkinshaw
7 months ago

Replying to nacin:

Replying to swalkinshaw:

Are these numbers based on the average or the sum of 10000 iterations?

I'd identify one problem with these benchmarks. get_file_data() and parse_ini_file() both hit the filesystem. json_decode() does not. If you didn't account for that, well, that I/O hit is pretty significant. If you did account for it, then I'd suggest that benchmarking this at high iterations isn't all that useful, since it'd only ever be run a few times on a pageload anyway.

They were the sum of all iterations. However all of them did hit the filesystem. I'd be glad to benchmark more real world numbers. If you could contribute some statistics about the number of plugins from wordpress.com hosting such as average, median, p10, p90, etc, then those could be run to see the actual overhead.

  • Uniformity: since JSON has a spec and built-in parsers in basically every language, it doesn't necessarily matter how you format whitespace for example. But with the current file headers, there's no uniformity and it can cause problems. Here's an example from the bug above:

I don't really have a problem with this. Only WP needs to do this parsing.

I don't understand this. Most configuration files are only parsed by their own application/framework and nothing externally, yet they all choose a sane standard.

As I indicated originally, I totally understand the desire and the use case. I just don't believe it is a complexity we have any need to introduce right now, regardless of format (json v yaml).

Let's be realistic here: if you were starting from scratch, JSON is less complex. I'm assuming you're talking about the complexity of migrating to a new solution and obviously that's not easy.

#26 @schlessera
8 weeks ago

As an additional argument in favour of a separate metadata file (whatever the exact format):

My themes all use a task runner (gulp) and have their stylesheet in an assets folder, in standard & minified form using content-hashed cache-busting in the file name (i.e. assets/styles/mytheme-e5d74a3d.min.css).

Nevertheless, I need to keep an empty style.css stub file in the root folder, as this is the only way to identify my theme to WordPress. This is an arbitrary folder structure lock-in that goes against many best practices found on other platforms.

Although I would heartily welcome a JSON file (even reusing composer.json would be fine, as it is pretty much a de-facto standard in the PHP world), any format would be fine as long as the "package" (plugin/theme/whatever else comes up) metadata is found in a separate metadata file.

EDIT: WordPress core even allows you to specify a different URI for the stylesheet using the stylesheet_uri filter, but it will scan the root style.css nevertheless for metadata: https://developer.wordpress.org/reference/hooks/stylesheet_uri/

Last edited 8 weeks ago by schlessera (previous) (diff)

#27 @DvanKooten
7 weeks ago

YES PLEASE.

On top of all already mentioned benefits, this'll ditch the dependency on get_file_data() to read the plugin/theme information making it much easier to get that same info from outside of WordPress. Gulp was mentioned already but there's loads more of course.

wp_get_theme() and get_plugin_data() could take care of this in a backwards compatible way, so that can't be a reason not do this.

Note: See TracTickets for help on using tickets.