将 css 文件导入 es6 returns 字符串而不是对象
import css file into es6 returns string instead of object
TL;DR
我正在将 css 文件导入打字稿模块,但导入解析为字符串而不是对象。谁能告诉我为什么我没有得到对象??
例子
// preview.ts
import test from './src/assets/test.theme.css';
// also tried this:
// import * as test from './src/assets/test.theme.css';
console.log('typeof test: ', typeof test);
console.log(test);
控制台输出
详细解释
实际上,我正在尝试为我的 Angular12 组件库设置一个 Storybook。
为了提供各种主题,我想使用@etchteam/storybook-addon-css-variables-theme
插件,在其文档中引用了Webpack的内联加载器语法。
import myTheme from '!!style-loader?injectType=lazyStyleTag!css-loader!./assets/my-theme.css';
将此应用到我的代码时,我的浏览器控制台开始抱怨
Error: myTheme.use is not a function
在我的研究过程中,我发现导入的样式表不是经过评估的 javascript 对象,而是作为包含样式加载器生成的源代码的字符串提供的。
我也认识到,这个问题不是特定于样式加载器,而是所有其他加载器都会发生,例如css-加载器、原始加载器等
这个问题也与内联加载器语法无关,因为它也与在简约的 webpack 配置中定义的加载器一起出现。
环境:
- Angular 12
- Webpack 5
复制
我设置了一个GIT repo reproducing the issue。
自述文件解释了重现和问题。
我认为您的 Webpack
配置有误。你嵌套了 rules
属性,而你应该嵌套 use
:
{
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
}
对不起,但我必须恢复我的最后声明。 @Akxe 的评论没有解决我的问题。
现在我的导入语句 (import * as test from '...'
) 解析为一个对象,但它仍然不正确。
我设置了一个GIT Repo to reproduce the issue。 readme.md
文件解释了重现和问题。
看起来 Webpack 不是 executing/evaluating 加载程序的 return 值。
顺便说一句。这不仅仅是 css-loader 的情况。 raw-loader、sass-loader、style-loader 等的结果保持不变
My final goal is to lazily load my theme files into a storybook.
I try to follow the documentation of the @etchteam/storybook-addon-css-variables-> theme.
我的问题终于解决了!
分析
这里的主要问题是 @angular-devkit/build-angular
包生成的 webpack 配置。我能够通过调试一个新的 angular12 应用程序来分析它(你可以查看 here)。
通过在 /node_modules/@angular-devkit/build-angular/src/utils/webpack-browser-config.js
处设置断点,函数:generateWebpackConfig(...)
,我可以在调试器中检查最终的 webpackConfig
对象。
相关的 rule 看起来像这样:
The important part here is the rule setting the module type to asset/source
, instructing webpack not to evaluate the loader's result.
解决方案概念 1:内联加载器
在alexander-kait and his great hints at this issue的帮助下,
我能够找到一个内联加载器语法来覆盖 webpack 的模块声明:
import Test from 'test.css.webpack[javascript/auto]!=!!!style-loader?injectType=lazyStyleTag!css-loader!./test.css';
console.log(typeof Test); // output: object
console.log(Test); // output: Object { use: () => void, unuse: () => void }
Test.use(); // this should usually be called by a theme switcher...
我不太确定这里的 url 模式,因为它似乎是一个未记录的功能,但我认为它类似于 <query-pattern>.webpack[<module-type>]!=!<loaders><query>
.
但是,由于这是一个未记录的功能,我不太愿意使用它。
解决方案概念二:webpackConfig自定义
由于我处于故事书上下文中,因此我决定根据 storybook documentation.
自定义 webpack 配置
我的解决方案需要设置命名约定(例如 *.theme.css
)。
// .storybook/main.js
module.exports = {
webpackFinal: async (config) => {
// exclude *.theme.css from the *.css ruleset
config.module.rules.find(rule => '.css'.match(rule.test)).exclude = [ /\.(?:theme\.css)$/i ];
// add a rule for *.theme.css
config.module.rules.push({
test: /\.(?:theme\.css)$/i,
use: [
{ loader: 'style-loader', options: { injectType: 'lazyStyleTag' } },
'css-loader',
],
});
},
};
有了这些规则,我现在可以简单地执行以下操作:
// preview.js
import LightTheme from './light.theme.css';
import DarkTheme from './dark.theme.css';
setupThemeSwitcher(LightTheme, DarkTheme);
Please note that the setupThemeSwitcher
function is just pseudocode merely there for the example. In reality I'm using the @etchteam/storybook-addon-css-variables-theme addon...
除了我正在加载 .scss 文件外,我在故事书和这个扩展中遇到了非常相似的问题。
我简单地调整了解决方案 2 以适合我的 .scss 案例,它就像一个魅力。
我无法使解决方案 1 起作用,但如前所述,这听起来很老套,而我认为解决方案 2 更简洁。
非常感谢分享这个解决方案,我苦苦挣扎了几个小时。
TL;DR
我正在将 css 文件导入打字稿模块,但导入解析为字符串而不是对象。谁能告诉我为什么我没有得到对象??
例子
// preview.ts
import test from './src/assets/test.theme.css';
// also tried this:
// import * as test from './src/assets/test.theme.css';
console.log('typeof test: ', typeof test);
console.log(test);
控制台输出
详细解释
实际上,我正在尝试为我的 Angular12 组件库设置一个 Storybook。
为了提供各种主题,我想使用@etchteam/storybook-addon-css-variables-theme
插件,在其文档中引用了Webpack的内联加载器语法。
import myTheme from '!!style-loader?injectType=lazyStyleTag!css-loader!./assets/my-theme.css';
将此应用到我的代码时,我的浏览器控制台开始抱怨
Error: myTheme.use is not a function
在我的研究过程中,我发现导入的样式表不是经过评估的 javascript 对象,而是作为包含样式加载器生成的源代码的字符串提供的。
我也认识到,这个问题不是特定于样式加载器,而是所有其他加载器都会发生,例如css-加载器、原始加载器等
这个问题也与内联加载器语法无关,因为它也与在简约的 webpack 配置中定义的加载器一起出现。
环境:
- Angular 12
- Webpack 5
复制
我设置了一个GIT repo reproducing the issue。
自述文件解释了重现和问题。
我认为您的 Webpack
配置有误。你嵌套了 rules
属性,而你应该嵌套 use
:
{
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
}
对不起,但我必须恢复我的最后声明。 @Akxe 的评论没有解决我的问题。
现在我的导入语句 (import * as test from '...'
) 解析为一个对象,但它仍然不正确。
我设置了一个GIT Repo to reproduce the issue。 readme.md
文件解释了重现和问题。
看起来 Webpack 不是 executing/evaluating 加载程序的 return 值。
顺便说一句。这不仅仅是 css-loader 的情况。 raw-loader、sass-loader、style-loader 等的结果保持不变
My final goal is to lazily load my theme files into a storybook. I try to follow the documentation of the @etchteam/storybook-addon-css-variables-> theme.
我的问题终于解决了!
分析
这里的主要问题是 @angular-devkit/build-angular
包生成的 webpack 配置。我能够通过调试一个新的 angular12 应用程序来分析它(你可以查看 here)。
通过在 /node_modules/@angular-devkit/build-angular/src/utils/webpack-browser-config.js
处设置断点,函数:generateWebpackConfig(...)
,我可以在调试器中检查最终的 webpackConfig
对象。
相关的 rule 看起来像这样:
The important part here is the rule setting the module type to
asset/source
, instructing webpack not to evaluate the loader's result.
解决方案概念 1:内联加载器
在alexander-kait and his great hints at this issue的帮助下, 我能够找到一个内联加载器语法来覆盖 webpack 的模块声明:
import Test from 'test.css.webpack[javascript/auto]!=!!!style-loader?injectType=lazyStyleTag!css-loader!./test.css';
console.log(typeof Test); // output: object
console.log(Test); // output: Object { use: () => void, unuse: () => void }
Test.use(); // this should usually be called by a theme switcher...
我不太确定这里的 url 模式,因为它似乎是一个未记录的功能,但我认为它类似于 <query-pattern>.webpack[<module-type>]!=!<loaders><query>
.
但是,由于这是一个未记录的功能,我不太愿意使用它。
解决方案概念二:webpackConfig自定义
由于我处于故事书上下文中,因此我决定根据 storybook documentation.
自定义 webpack 配置我的解决方案需要设置命名约定(例如 *.theme.css
)。
// .storybook/main.js
module.exports = {
webpackFinal: async (config) => {
// exclude *.theme.css from the *.css ruleset
config.module.rules.find(rule => '.css'.match(rule.test)).exclude = [ /\.(?:theme\.css)$/i ];
// add a rule for *.theme.css
config.module.rules.push({
test: /\.(?:theme\.css)$/i,
use: [
{ loader: 'style-loader', options: { injectType: 'lazyStyleTag' } },
'css-loader',
],
});
},
};
有了这些规则,我现在可以简单地执行以下操作:
// preview.js
import LightTheme from './light.theme.css';
import DarkTheme from './dark.theme.css';
setupThemeSwitcher(LightTheme, DarkTheme);
Please note that the
setupThemeSwitcher
function is just pseudocode merely there for the example. In reality I'm using the @etchteam/storybook-addon-css-variables-theme addon...
除了我正在加载 .scss 文件外,我在故事书和这个扩展中遇到了非常相似的问题。 我简单地调整了解决方案 2 以适合我的 .scss 案例,它就像一个魅力。 我无法使解决方案 1 起作用,但如前所述,这听起来很老套,而我认为解决方案 2 更简洁。 非常感谢分享这个解决方案,我苦苦挣扎了几个小时。