如何在没有"~"的情况下从 sass 加载器中的node_modules导入样式表



我正在设置我的Storybook实例以从Rails应用程序加载样式,但它未能在我的main.scss文件中加载导入,两者都是来自node_modules:的样式表

@import 'react-table/react-table.css';
@import 'animate.css';

我在尝试运行我的故事书实例时收到错误:

ERROR in ./app/javascript/stylesheets/main.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js??ref--9-2!./app/javascript/stylesheets/main.scss)
Module not found: Error: Can't resolve './animate.css' in '<my_project>/app/javascript/stylesheets'
@ ./app/javascript/stylesheets/main.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js??ref--9-2!./app/javascript/stylesheets/main.scss) 4:40-111
@ ./app/javascript/stylesheets/main.scss
@ ./stories/1-Table.stories.js
@ ./stories sync ^./(?:(?:(?!.)(?:(?:(?!(?:|/).).)*?)/)?(?!.)(?=.)[^/]*?.stories.js/?)$
@ ./.storybook/generated-entry.js
@ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/generated-entry.js (webpack)-hot-middleware/client.js?reload=true&quiet=true
ERROR in ./app/javascript/stylesheets/main.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js??ref--9-2!./app/javascript/stylesheets/main.scss)
Module not found: Error: Can't resolve './react-table/react-table.css' in '<my_project>/app/javascript/stylesheets'
@ ./app/javascript/stylesheets/main.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js??ref--9-2!./app/javascript/stylesheets/main.scss) 3:40-127
@ ./app/javascript/stylesheets/main.scss
@ ./stories/1-Table.stories.js
@ ./stories sync ^./(?:(?:(?!.)(?:(?:(?!(?:|/).).)*?)/)?(?!.)(?=.)[^/]*?.stories.js/?)$
@ ./.storybook/generated-entry.js
@ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/generated-entry.js (webpack)-hot-middleware/client.js?reload=true&quiet=true

这是我工作项目的一部分目录:

.
├── .storybook
│   ├── main.js
│   └── preview-head.html
├── app
│   ├── assets
│   │   └── stylesheets
│   │       ├── _base.scss
│   └── javascript
│       ├── packs
│       │   ├── application.js
│       │   └── server_rendering.js
│       └── stylesheets
│           ├── _variables.scss
│           └── main.scss
├── babel.config.js
├── postcss.config.js
├── stories
│   ├── 0-Welcome.stories.js
│   └── 1-Table.stories.js
├── yarn-error.log
└── yarn.lock

这是我在Storybook的main.js中的尝试,让sass-loader知道我想在不加"~"号的情况下导入文件,因为web应用程序端无法正确加载样式,所以不能更改我项目的webpack配置。

const path = require('path')
module.exports = {
stories: ['../stories/**/*.stories.js'],
addons: ['@storybook/addon-actions', '@storybook/addon-links'],
webpackFinal: async config => {
config.module.rules.push({
test: /.scss$/,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
includePaths: [
'../node_modules/animate',
'../node_modules/react-table'
]
}
}
],
include: [
path.resolve(__dirname, '../node_modules'),
path.resolve(__dirname, '../app/javascript/stylesheets'),
path.resolve(__dirname, '../app/assets/stylesheets')
]
})
return config
}
}

我做得不对吗?

如果您使用的是Webpack4.x,那么您只需要在Webpack配置文件中添加几个别名,如下所示:

// Your Webpack config file
...
webpackFinal: async config => {
config.module.resolve.alias = {
'animate-css': path.resolve(__dirname, '../../../node_modules/animate.css'),
'react-table': path.resolve(__dirname, '../../../node_modules/react-table-v6/react-table.css'),
}
...
}

然后您可以在main.scs:中导入这些别名

@import 'animate-css';
@import 'react-table';

您还需要从sass加载程序中删除选项。我指定了node_modules的路径,假设它与app目录位于同一级别,并且包react-table不包含CSS文件,所以我指定了v6。

使用includePaths完成Webpack 5的工作示例

这里有一个完整的例子,不确定为什么includePaths不适用于OP,或者是否有其他限制,但它对我来说很有用,因为我可以直接从main.scss@use "normalize.css/normalize.css"而不使用波浪号。

这就产生了dist/main.css,它是一个缩小的CSS,包含两个:

  • 我们的main.scss
  • normalize.css通过node_modules

两者的效果可以在index.html测试文件中看到。

webpack.config.js

const path = require('path');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const nodeModulesPath = path.resolve(__dirname, 'node_modules');
module.exports = {
entry: {
main: ['./main.scss'],
},
mode: 'none',
module: {
rules: [
{
test: /.(scss|css)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: "sass-loader",
options: {
sassOptions: {
includePaths: [nodeModulesPath],
},
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
optimization: {
minimizer: [
new CssMinimizerPlugin(),
],
minimize: true,
}
};

main.scss

@use "normalize.css/normalize.css";
body {
background-color: red;
}

index.html

<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>Sass import</title>
<link rel="stylesheet" href="dist/main.css">
</head>
<body>
<p>Hello</p>
</body>
</html>

软件包.json

{
"name": "webpack-cheat",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "webpack",
"sass": "rm -f dist/main.css && sass main.scss dist/main.css"
},
"author": "Ciro Santilli",
"license": "MIT",
"devDependencies": {
"css-loader": "5.2.4",
"css-minimizer-webpack-plugin": "3.0.2",
"mini-css-extract-plugin": "2.1.0",
"normalize.css": "8.0.1",
"sass": "1.32.11",
"sass-loader": "11.0.1",
"style-loader": "2.0.0",
"webpack": "5.36.1",
"webpack-cli": "4.6.0",
"webpack-dev-server": "3.11.2"
}
}

最新更新