Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS example #70

Closed
AustinGil opened this issue Oct 17, 2020 · 13 comments
Closed

CSS example #70

AustinGil opened this issue Oct 17, 2020 · 13 comments

Comments

@AustinGil
Copy link

AustinGil commented Oct 17, 2020

Is there any chance you have a basic example of how I can use this to inject some CSS into my bundle?

I have it almost working, but my build never completes. Im useing webpack loader utils to generate a path like this

const cssPath = loaderUtils.interpolateName(
    this,
    '[path][name].[hash:base64:7].css',
    {
      content: 'p { text-align: center }'
    }
  );

But when I log the cssPath, it looks like it just builds onto itself

/example-project/src/styles.MINrvtm.css
/example-project/src/styles.MINrvtm.MINrvtm.css
/example-project/src/styles.MINrvtm.MINrvtm.MINrvtm.css
/example-project/src/styles.MINrvtm.MINrvtm.MINrvtm.MINrvtm.css
/example-project/src/styles.MINrvtm.MINrvtm.MINrvtm.MINrvtm.MINrvtm.css
@larixer
Copy link
Member

larixer commented Oct 17, 2020

@Stegosource Where do you use webpack-virtual-modules?

@AustinGil
Copy link
Author

Thanks. Right now all Im trying to do is tell webpack to inject some CSS into whatever output CSS file. I've been trying to copy another project that does something similar and uses this pattern with virtual modules. My project looks something like this:

// virtualModules.js
const VirtualModulesPlugin = require('webpack-virtual-modules');
module.exports = new VirtualModulesPlugin();
// loader.js
const loaderUtils = require('loader-utils');
const virtualModules = require('./virtualModules')

async function loader(input, inputSourceMap) {
  const cssPath = loaderUtils.interpolateName(
    this,
    '[path][name].[hash:base64:7].css',
    {
      content: 'p { text-align: center }'
    }
  );

  console.log(cssPath)

  virtualModules.writeModule(cssPath, 'p { text-align: center }');

  const importLine = `import '${cssPath}';`;
  this.callback(null, importLine);
}

module.exports = loader
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const virtualModules = require('./virtualModules')

module.exports = {
  entry: {
    app: './src/index.js',
  },
  plugins: [
    new HtmlWebpackPlugin(),
    new MiniCssExtractPlugin(),
    virtualModules,
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: path.resolve('./loader.js'),
          },
          'css-loader',
        ],
      },
    ],
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

@larixer
Copy link
Member

larixer commented Nov 16, 2020

Closing the issue, as it seems more a question than an actual issue which will be unlikely answered here

@larixer larixer closed this as completed Nov 16, 2020
@AustinGil
Copy link
Author

ok... :(

@larixer
Copy link
Member

larixer commented Nov 16, 2020

@AustinGil I can only propose an idea where your code does not look quite right. When in the code you do virtualModules.writeModule(cssPath, 'p { text-align: center }');, it has the same effect as writing the file - it changes the file timestamp each time and webpack sees it as a change to the file even though the contents of the file is the same. You should probably check i n the code if the contents of the file changed - and if it is not the case - avoid calling writeModule

@AustinGil
Copy link
Author

Thanks @larixer. I actually meant that last comment kind of jokingly. Didn't mean for you to keep this open and no need to explain further. I think you're right that this was more of a question and no need to keep the issue open.

@halostatue
Copy link

I found this issue because I was looking for an example, and think that this would be an excellent addition to the documentation. Here’s what I did (I’m using Vue CLI, so I may get some of the normal Webpack details incorrect):

// webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VirtualModulesPlugin = require('webpack-virtual-modules')

const cssVars = Object.keys(clientTheme).map((key) => `  --component-${key}: ${clientTheme[key]};`).join('\n')
const theme = `:root {\n${cssVars}\n}\n`
const virtualModules = new VirtualModulesPlugin({ 'node_modules/theme.css': theme })

module.exports = {
  entry: {
    app: './src/index.js',
  },
  plugins: [
    new HtmlWebpackPlugin(),
    virtualModules,
    new MiniCssExtractPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
    ],
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};
import Vue from 'vue'
import App from './src/App'
import 'theme.css' // <-- This does the magic

new Vue({
  el: '#app',
  render: (h) => h(App),
})

This module has let me accomplish something that I’ve been trying to do for months.

@AustinGil
Copy link
Author

Oh that's really interesting @halostatue. Thanks for taking the time to share. I'm trying to use this in a library, so it may not work for me, but it's worth playing around with.

In any case, I think this WILL be helpful for some project in the future :)

@halostatue
Copy link

It should work even for a library, but as a consumer of libraries where I serve with a strict CSP policy…please make sure you configure Webpack to extract the CSS into a separate file, because I disallow the use of style attributes (the default if Webpack isn’t set up for extraction).

@larixer I think that this is definitely worth adding to the README or in an example.

@larixer
Copy link
Member

larixer commented Dec 11, 2020

@halostatue To be fair I don't see how it is much different from the current example

@halostatue
Copy link

Technically, it is the same as the current example. But there’s a conceptual break for people who don’t really understand the internals of Webpack and have to deal with it. I’ve literally spent months trying to figure out how to inject some dynamically generated CSS into my bundle (we use a single repo to generate ~10 different themed versions for different clients). This is a non-obvious solution to this particular problem to most people who are just having to work with Webpack.

The recommendation for adding this to the documentation is to make the solution to dynamic CSS injection discoverable—and I’m hoping that if it’s more discoverable, the next person in my situation, or in @AustinGil’s situation, simply has a solution available instead of having to figure it out from scratch. This plugin is spectacular in its power (and it may also help with other plug-in type problems that I have), but IMO could use a wider variety of examples of just what it can do.

@AustinGil
Copy link
Author

Yeah, as I take a second look, I can see how this could be used for a library. Will need to test it.

I also agree that this would make a good example. I looked through this and compared to the one in the README and find this one to be intuitive. While the other is still a bit hard for me to get what's going on. That may just be me, but the example in this thread seems to make a bit more sense on what I need to do.

@larixer
Copy link
Member

larixer commented Dec 12, 2020

@AustinGil @halostatue Feel free to open PR and update current example or add CSS example next to the current one

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

No branches or pull requests

3 participants