style-loader icon indicating copy to clipboard operation
style-loader copied to clipboard

Add ID's to <style> tags

Open alex-mm opened this issue 7 years ago • 17 comments

Why ?

I have many components. And I can not use 'ExtractTextPlugin' for special reasons.

I would like to distinguish which component and the version number to use.

How ?

I found the attrs

require('style-loader?{attrs:{id: "style-tag-id"}}!style.css');

But the information of the component can only be obtained in the compilation of each file.

So

I would like to make this change in 'style-loader/index.js'.

	var findPackage = require('find-package');
        ...
	if(this.cacheable) this.cacheable();
	var query = loaderUtils.getOptions(this) || {};
	var pkg = findPackage(this.resourcePath) || {};
	if (query.attrs) {
		Object.keys(query.attrs).forEach(function(key) {
			query.attrs[key] = query.attrs[key].replace(/\[name\]/ig, pkg.name).replace(/\[version\]/ig, pkg.version);
		});
	}
        return ...

Then

I use it like this

require('style-loader?{attrs:{component: "[name]@[version]"}}!style.css');

The result:

If it is acceptable ? Or is there any other solution?

Fork: https://github.com/alex-mm/style-loader/blob/master/index.js#L7-L17

alex-mm avatar Apr 18 '17 08:04 alex-mm

@alex-mm What's the particular usecase for this in terms of development ? 😛

michael-ciniawsky avatar Apr 18 '17 11:04 michael-ciniawsky

@michael-ciniawsky

It is mainly to help developers identify which components and versions.

When the dependent components are many, there are some common dependencies, especially when the dependent version is different, there will be style coverage problems, it is difficult to find which component is wrong version, there will also be repeated insert the situation, you are It is hard to see which component is repeated.

By adding the information on the 'attr', you can clearly find out the problem.

By making the private package, we've done it, it's really useful.

alex-mm avatar Apr 19 '17 02:04 alex-mm

I would appreciate it too.

It is kind of frustrating to be able to add only "static values" to the attributes of the injected <style> elements...

francoismassart avatar Oct 02 '17 09:10 francoismassart

We could maybe include the filename as attribute, but I'm still not really convinced by the idea. If this is really wanted someone feel free/please open a PR for further discussion

michael-ciniawsky avatar Nov 08 '17 22:11 michael-ciniawsky

It might help you to remove stylesheet by id in unuse()/unref()

budarin avatar Dec 15 '17 17:12 budarin

Really need this feature, like webpackChunkName, so we can distinguish source of styles.

kimown avatar Jan 27 '18 08:01 kimown

I'm using this:

    options: {
      attrs: { title: 'less' }
    }

It renders, however for some strange reason the style is not applied to the page...

alextrastero avatar Feb 07 '18 11:02 alextrastero

+1 would like this to help debug styling issues

pixeldrew avatar Mar 06 '18 15:03 pixeldrew

@pixeldrew PR welcome :+1:

alexander-akait avatar Mar 06 '18 16:03 alexander-akait

Don't use:

options: {
  attrs: { title: 'less' } // title specifies alternative style sheet sets
}

But maybe:

options: {
  attrs: { data-debug: 'less' }
}

?

alextrastero avatar Mar 06 '18 16:03 alextrastero

@michael-ciniawsky PR #336

alex-mm avatar Jul 25 '18 14:07 alex-mm

What if the attrs option accepted webpack placeholders via interpolateName from loader-utils?

options: {
  attrs: { data-source: '[path]_[name]' }
}

akdetrick avatar Apr 15 '19 16:04 akdetrick

PR welcome

alexander-akait avatar Apr 15 '19 16:04 alexander-akait

Simple temporary solution without modily the lib(version 0.23.1):

  • ./build/loader.js
const path = require('path')
const loader = require('style-loader')

module.exports = function () {
}

module.exports.pitch = function (request) {
  const result = loader.pitch.call(this, request)
  const index = result.indexOf('options.transform = transform\n')
  if (index <= -1) return result
  const insertIndex = index - 1

  // eslint-disable-next-line prefer-destructuring
  const resourcePath = this.resourcePath
  const relativePath = path.relative(path.resolve(__dirname, '..'), resourcePath)

  const insertAttr = `
if (typeof options.attrs !== 'object') {
  options.attrs = {}
}
options.attrs["source-path"] = '${relativePath}' // do anything you want
  `

  return result.slice(0, insertIndex) + insertAttr + result.slice(insertIndex)
}
  • webpack config
{
  test: /\.css$/,
  use: [
    './build/style-loader',
     'css-loader'
  ]
}

The loader output code will be like:


var options = {"attrs":{"name":"aa"},"hmr":true}

if (typeof options.attrs !== 'object') {
  options.attrs = {}
}
options.attrs["source-path"] = 'src/components/color-picker.less'

options.transform = transform
options.insertInto = undefined;

The element in header:

image

oustn avatar May 10 '20 06:05 oustn

any news regards webpack placeholders? I'm tryinig to insert the file name as a source attribute and [name] is being ignored...

erezactionbar avatar Jul 20 '20 21:07 erezactionbar

I could really use this in runtime for caching. I have multiple apps bundling the same ui library (not externalised for a reason), resulting in the insertion of the same CSS and the only seemingly possible way to avoid that, is by calculating a content hash in build-time and then pass it to the style tag with an attribute data-hash (I currently calculate the hash in runtime, which is very costly, can take up to few seconds). WDYT? is there any other way to accomplish this?

adi518 avatar Dec 06 '20 16:12 adi518

 './build/style-loader',

我直接报this.getOptions相关错误

zhushibo avatar Jul 20 '22 09:07 zhushibo