Dependency library unable to access relative node modules imports - reactjs

I need to add a UI toolkit dependency in my project. The dependency injects two libraries in node-modules
—toolkit
—toolkit-core
—toolkit-ui
I need to use files from toolkit-ui. But the toolkit-ui is importing relative dependency as below:
#import "toolkit-core/tools"
When the project compiles it gives me below error :
ERROR in ./css/app.scss (./node_modules/css-loader!./node_modules/postcss-loader/src??ref--5-2!./node_modules/resolve-url-loader!./node_modules/sass-loader/dist/cjs.js!./css/app.scss)
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
#import "toolkit-core/tools";
^
File to import not found or unreadable: toolkit-core/tools.
My webpack set up as below
const { resolve, join} = require('path');
const autoprefixer = require('autoprefixer');
const postCssLoader = {
loader: 'postcss-loader',
options: {
plugins: function() {
return [autoprefixer({ browsers: ['last 2 versions', 'ie 10'] })];
}
}
};
module.exports = (projectDir) => [
…
{
test: /\.(scss|css)$/,
use: [
'style-loader', 'css-loader', postCssLoader, 'resolve-url-loader',
{
loader: 'sass-loader',
options: {
sourceMap: true,
minimize: true,
includePaths: [path.join(__dirname, 'node_modules')],
}
}
]
},
…
]
Can someone please suggest how can I resolve this?
Thanks

I resolved above.
I was importing webpack loaders from a common build directory. I was trying to override it by adding a new rule for scss|css. But that didn't seem to work. Webpack used the first rule for scss|css loaders.
However if I replace that rule by my in app rule. It works.

Related

Why does my SASS style only apply partially?

I'm creating a react component library. Styling needs to be isolated, apart from some global variables. My styling is not applying everywhere, only on some pages. Why is this and how can I fix it?
My webpack.config.js:
const webpack = require('webpack');
const path = require('path');
module.exports = async ({ config, mode }) => {
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
mode: 'local',
localIdentName:
'[name]-[local]-[hash:base64:3]',
},
import: true,
importLoaders: true,
}
},
{
loader: 'sass-loader',
},
{
loader: 'sass-resources-loader',
options: {
resources: [
path.resolve(__dirname, '../src/styles/variables/_variables.scss'),
path.resolve(__dirname, '../src/styles/variables/_header.scss'),
path.resolve(__dirname, '../src/styles/variables/_footer.scss')
]
}
}
],
});
return config;
};
For example: I have a module "Checkbox". The story for the module is below. The first story is styled, the second story is not.
stories.add('Empty', () => (
<Checkbox />
));
stories.add('With Label', () => (
<Checkbox classes={propsClasses} field={'Field'} label={'Label'} />
));
EDIT:
With the webpack.config.js below, all the styles load. But then ALL the styles load on EVERY page. Which makes for duplicate style and no longer an isolated component.
const webpack = require('webpack');
const path = require('path');
module.exports = async ({ config, mode }) => {
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
mode: 'local',
localIdentName: '[local]',
},
import: true,
importLoaders: true,
}
},
{
loader: 'sass-loader',
},
{
loader: 'sass-resources-loader',
options: {
resources: [
path.resolve(__dirname, '../src/styles/variables/_variables.scss'),
path.resolve(__dirname, '../src/styles/variables/_header.scss'),
path.resolve(__dirname, '../src/styles/variables/_footer.scss')
]
}
}
],
});
return config;
};
Webpack bundles CSS files when they are required, the same way it bundles JS files when they are required. When using sass-loader, css-loader, and style-loader, the require will pass the Sass source code through those loaders and the result is JS code that will insert the transpiled CSS into a <style> element on the page at runtime. That JS code is what gets added to the bundle webpack creates.
I'm not familiar with sass-resources-loader, but per its README, This loader will #import your SASS resources into every required SASS module -- this is likely why you're seeing all of your styles imported for each module...?
To isolate your styles on a per-component basis, you probably want a .scss file for each component that contains styles for that component, and to require() that .scss file in its JS module. Because webpack processes each Sass file independently, as it's required, each component's Sass file will need to import any variables/mixins it needs. (It sounds like sass-resources-loader is trying to handle that for you, but not giving the desired results?)
How are you loading your Sass files currently?

Module not found: Error: Can't find options with ident 'postcss'

I'm new on stackoverflow to ask you a question that I never find on the internet... I hope I'm in the good website :)
So here is my problem : I would like to import some css files to a react application from node_modules dependencies. I use webpack for the developpement and I got an error I don't understand and that is in the title.
So here is the error details from the compiler :
ERROR in ./src/scss/app.scss
Module not found: Error: Can't find options with ident 'postcss'
# ./src/scss/app.scss 9:10-188
# ./src/app/App.js
# ./src/index.js
# multi (webpack)-dev-server/client?http://localhost:8080 (webpack)/hot/dev-server.js ./src
also, in the nav console I got this :
Error: Cannot find module '-!../../node_modules/css-loader/index.js?{"importLoaders":1}!../../node_modules/postcss-loader/lib/index.js??postcss!react-big-calendar/lib/css/react-big-calendar.css'
that is the content of my scss file cannot load css files.
App.scss :
exports.i(require("-!../../node_modules/css-loader/index.js?{\"importLoaders\":1}!../../node_modules/postcss-loader/lib/index.js??postcss!react-big-calendar/lib/css/react-big-calendar.css"), "");
You can check also my webpack config file :
const HtmlWebPackPlugin = require("html-webpack-plugin");
const htmlWebpackPlugin = new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
});
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
'postcss-loader'
]
}
]
},
plugins: [htmlWebpackPlugin],
resolve: {
extensions: ['.js', '.jsx', '.json', '.css']
}
};
What's wrong with my code ?
Thank you very much to help me ! If I'm not very clear, please ask me any other informations
You probably need to change your postcss-loader config to this. Depends really on which version of the loader you have, not needed from 4.0.0 (https://github.com/webpack-contrib/postcss-loader/releases/tag/v4.0.0)
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
},
}

Storybook Global Scss variables

CLI Tool: Storybook
Framework: Vue/ Nuxt
Issue: I'm trying to pull in global SCSS variables to Storybook Stories so they run the components the same way as they do in Nuxt, I've tried the custom webpack config with sass-resources-loader but had no luck, just wanted to check if anyone else has already solved this problem
It seems to be an issue with Storybook handling multiple rules.
I solved it by a work around.
You can read the blog i wrote for detailed explaination here.
Below is my webpack config - main.js :
webpackFinal: async (config, { configType }) => {
config.module.rules.map((rule) => {
if (rule.oneOf) {
rule.oneOf = rule.oneOf.slice().map((subRule) => {
if (subRule.test instanceof RegExp && subRule.test.test('.scss')) {
return {
...subRule,
use: [
...subRule.use,
{
loader: require.resolve('sass-resources-loader'),
options: {
resources: [
path.resolve(__dirname, '../src/styles/_common.scss')
]
}
}
],
}
}
return subRule;
});
}
return rule;
});
return config;
},
Hope this helps someone!
I encountered the issue where global SASS variables were causing Storybook for Vue to fail.
For me, creating a webpack.config.js file in the .storybook folder with the below configuration solved my problem:
module.exports = (storybookBaseConfig, configType, defaultConfig) => {
defaultConfig.module.rules.push(
{
resourceQuery: /module/,
use: [
{
loader: 'vue-style-loader',
options: {
sourceMap: false,
shadowMode: false
}
},
{
loader: 'css-loader',
options: {
sourceMap: false,
importLoaders: 2,
modules: true,
localIdentName: '[name]_[local]_[hash:base64:5]'
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false,
indentedSyntax: true,
data: '#import "#/sass/_variables.scss";'
}
}
]
}
);
return defaultConfig;
};
Note the line data: '#import "#/sass/_variables.scss";' needs to match the file path for the SASS file with variables in your project.
This section of config was retrieved from Vue CLI 3 by running vue inspect > output.js and then copying the config for the rule test: /\.sass$/.
You need to add the scss rule in your .storybook/webpack.config.js for storybook to parse scss.
const path = require('path');
const scss = {
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
};
module.exports = (storybookBaseConfig, configType, defaultConfig) => {
defaultConfig.module.rules.push(scss);
return defaultConfig;
};
You may also need to install the appropriate loaders:
yarn add -D vue-style-loader sass-loader css-loader
For anybody who can actually get Storybook to read SCSS files but can't get it to read the global variables file, do this in your custom webpack config:
module: {
rules: [
// Apply loader
{
test: /\.scss$/,
loaders: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
prependData: '#import "path/to/global.scss";',
},
},
],
},
],
}
If your components do not get styles applied when run in the Storybook component explorer UI, just import SASS styles in your main Storybook config/storybook/config.js (in previous versions was by default at storybook/config.js) like so:
// Import Styles
import '../../src/assets/styles/index.scss';
Usually you'd have your styles and plugins imported in your src/main.js / src/main.ts but you also need to do this in Storybook config, as when running Storybook it's not running the whole Vue app but just those individual components.

ts-loader / css-loader not being able to import/resolve file

Trying to add css modules using style-loader and css-loader. Having a hard time figuring this out. I'm also not sure whether it's ts-loader to blame or css-loader.
webpack.config.js
const path = require('path');
module.exports = env => {
return {
devtool: "inline-source-map",
entry: "./src/index.tsx",
output: {
path: path.resolve(__dirname, "/public"),
filename: "build/app.js"
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".json"],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
},
{
test: /\.css$/,
loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
}
]
}
}
}
component
import styles from "./Main.css"; // TS2307: Cannot find module './Main.css'.
P.S. I tried using the extract-text-webpack-plugin, but that only messed up everything even more making the errors overwhelming
So since this doesn't seem like a popular problem I managed to find the solution. Hope this will help anyone who struggles with ts-loader + css-loader.
1) Add .d.ts file that handles .css extensions
// I put it in root, but could be anywhere
// <root>/defs.d.ts
declare module "*.css" {
var styles: { [key: string]: string };
export = styles
}
2) Since I use Webpack 3.x, change style to style-loader in webpack.config.js
module: {
rules: [
//...
{
test: /\.css$/,
loader: 'style-loader!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
}
]
}
3) Import styles as * in component file
// In Main.tsx
import * as styles from "./Main.css";
// Usage
<div className={styles.nameOfClass} />
4) In tsconfig.json add .d.ts file to the include part. In my case its...
"include": [
"src",
"./defs.d.ts"
],
Restart webpack-dev-server or whatever and it should be good to go (hopefully).
Happy coding!

Webpack loader fails when importing .css in react_on_rails app?

I am trying to use react-datetime on my react-on-rails app. To make the datetime work out of the box, I need to import the CSS mentioned on their GH page.
On my app, I copy/paste the CSS into a file I named DateTime.css:
...
import DateTime from 'react-datetime';
import '../../schedules/stylesheets/DateTime.css';
...
export default class AddDate extends React.Component {
But it gives me this error:
VM45976:1 Uncaught Error: Module parse failed: /Users/some/path/to/my/project/App/components/schedules/stylesheets/DateTime.css Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| .rdt {
| position: relative;
| }
It seems like the CSS loader is not working. I tried this on pure react app (create-react-app) and it worked. It broke when I did it inside react_on_rails.
This is my webpack config atm (standard out-of-the-box react_on_rails):
const webpack = require('webpack');
const { resolve } = require('path');
const ManifestPlugin = require('webpack-manifest-plugin');
const webpackConfigLoader = require('react-on-rails/webpackConfigLoader');
const configPath = resolve('..', 'config');
const { devBuild, manifest, webpackOutputPath, webpackPublicOutputDir } =
webpackConfigLoader(configPath);
const config = {
context: resolve(__dirname),
entry: {
'webpack-bundle': [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
'./app/bundles/App/startup/registration',
],
},
output: {
// Name comes from the entry section.
filename: '[name]-[hash].js',
// Leading slash is necessary
publicPath: `/${webpackPublicOutputDir}`,
path: webpackOutputPath,
},
resolve: {
extensions: ['.js', '.jsx'],
},
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'development', // use 'development' unless process.env.NODE_ENV is defined
DEBUG: false,
}),
new ManifestPlugin({ fileName: manifest, writeToFileEmit: true }),
],
module: {
rules: [
{
test: require.resolve('react'),
use: {
loader: 'imports-loader',
options: {
shim: 'es5-shim/es5-shim',
sham: 'es5-shim/es5-sham',
},
},
},
{
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
use: 'css-loader',
exclude: /node_modules/,
},
],
],
},
};
module.exports = config;
if (devBuild) {
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map';
} else {
console.log('Webpack production build for Rails'); // eslint-disable-line no-console
}
I am very new in webpack, and not sure how to I can add loaders to make it work, how can I apply the DateTime.css file that I have to be applied to react-datetime?
EDIT: added css-loader (also updated the webpack above). It is no longer complaining that I don't have the correct loader, but the CSS does not work.
{
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
use: 'css-loader',
exclude: /node_modules/,
},
],
There are 2 conceptually different ways to approach this.
1. Using CSS modules.
This way your CSS will end up bundled with your JS and as soon as webpack loads that JS module/bundle it will automatically append CSS style element into the head.
In my project I have this rule to do exactly that (note that we use both css-loader and style-loader):
{
test: /\.css$/,
use: ['style-loader', {
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]'
}
}]
}
More on css-loader modules at this link.
2. Using ExtractTextPlugin. This way all your CSS will be extracted into a separate file. The configuration requires 2 things: a plugin and loaders configuration created by the plugin:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
// Add this to your webpack plugins array
new ExtractTextPlugin('styles.css')
And add this to your rules:
{
test: /\.css$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader']
})
}
This will create one single styles.css file and put all CSS you import from JS into that file.

Resources