Skip to content
This repository has been archived by the owner on Oct 30, 2020. It is now read-only.

Definitions created only match the output when using style-loader and namedExport #5

Closed
Zalastax opened this issue Oct 16, 2016 · 4 comments

Comments

@Zalastax
Copy link
Contributor

The final output that the type definitions are supposed to match is very fragile.

E.g.

loaders: ['typings-for-css-modules-loader?sourceMap&modules'] creates an export of the css like

exports.locals = { "foo": "foo-1A72" }

which is not the exports.default that the definition expect.
loaders: ['style', 'typings-for-css-modules-loader?sourceMap&modules&importLoaders=1'} creates an export of the css like

exports.foo= "foo-1A72"

which I expected to be an object on exports.default but instead got the same behaviour as if namedExport was defined. See webpack/style-loader#local-scope-css and webpack-contrib/style-loader#77

I think changing the export from default to locals is correct and adding to the readme that style-loader requires namedExport. I've made some of those changes and fixed some others in my fork

@timse
Copy link
Contributor

timse commented Oct 16, 2016

Hey @Zalastax thanks for the work! Would you mind to open a pull-request?

I checked some of your fixes, I think it would make sense to open several there 😄 .

That being said, I am not entirely sure that i get your first issue, what exactly do you mean with the exports.locals part? Do you maybe have some example code so I can follow?

Again thanks for the work!

@Zalastax
Copy link
Contributor Author

npm test will create a file test/bundle.js with modules for each css file [1]. Updating webpack.config.babel.js to use the style-loader [2] adds a wrapper module around each module with css. This wrapper [3] moves the exports from exports.locals to export (i.e. named exports). To reflect this I would advise to use export = which would create a typescript definition like [4]. I think that is the preferred way of doing named exports as well, as it avoids the problem of invalid names and simplifies the code for that path. Let me know what you think and I'll make the changes and open some pull requests.

[1]

function(module, exports, __webpack_require__) {

    exports = module.exports = __webpack_require__(2)(); // 2 is css-loader base code
    // imports


    // module
    exports.push([module.id, "._3xa5lyhHp10qoUNQHktGL {\n  color: white;\n}\n\n._3FvfrYo1XzOMAEcFNpnMG6 {\n  color: green;\n}\n", ""]);

    // exports
    exports.locals = {
        "foo": "_3xa5lyhHp10qoUNQHktGL",
        "bar-baz": "_3FvfrYo1XzOMAEcFNpnMG6"
    };
 }

[2]

module: {
    loaders: [
      { test: /\.ts$/, loaders: ['babel', 'ts'] },
      { test: /example.css$/, loader: 'style!../src/index.js?modules' },
      { test: /example-camelcase.css$/, loader: 'style!../src/index.js?modules&camelCase' },
      { test: /example-namedexport.css$/, loader: 'style!../src/index.js?modules&namedExport' },
      { test: /example-camelcase-namedexport.css$/, loader: 'style!../src/index.js?modules&camelCase&namedExport' }
    ]
  }

[3]

function(module, exports, __webpack_require__) {

    // style-loader: Adds some css to the DOM by adding a <style> tag

    // load the styles
    var content = __webpack_require__(2); // 2 is our module with css seen above (numbers changed)
    if(typeof content === 'string') content = [[module.id, content, '']];
    // add the styles to the DOM
    var update = __webpack_require__(4)(content, {});
    if(content.locals) module.exports = content.locals;
    // Hot Module Replacement
    if(false) {
        // When the styles change, update the <style> tags
        if(!content.locals) {
            module.hot.accept("!!./../src/index.js?modules!./example.css", function() {
                var newContent = require("!!./../src/index.js?modules!./example.css");
                if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
                update(newContent);
            });
        }
        // When the module is disposed, remove the <style> tags
        module.hot.dispose(function() { update(); });
    }

[4]

interface IExampleCss {
  'foo': string;
  'bar-baz': string;
}
export = IExampleCss;

@timse
Copy link
Contributor

timse commented Oct 17, 2016

Hi @Zalastax thanks for the write up!
I remember once pondering about the whole exports.locals becoming the export thing and didn't really know what to make out of it.

I like your thinking, just one last question, taken from the typescript documentation, would that mean we need to go for import styles = require(...); ?

@Zalastax
Copy link
Contributor Author

You are right about import styles = require(...); being the only way to import such modules. Unfortunately I can't get that to work in a good fashion. microsoft/TypeScript#2709 and http://stackoverflow.com/a/36107464/497116 seem to suggest that requiring css is not well supported. export = is probably what should be aimed for in the future, but right now it's best to settle for the current implementation. I'll create pull requests for my changes and update the README to include a section about using style-loader.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants