StencilJS - How to import css/sass from node_modules? - javascript

I am trying to import a css file that has variables from a node_modules package.
I've attempted to copy from the stencil.config.ts, but it keeps dumping builds into the location I am trying to specify and can't find information for the next foot forward..
What I have right now is something like this:
type: "www",
dir: 'src/global',
copy: [
{ src: '../node_modules/package/design-tokens/dist/tokens.css', dest: 'themes' }
]
}
Right now I just need to go into the node_modules and reference a css file that has variables.
Thank you!

Have you tried to import the file directly from node modules in your global css file?
In stenil.config.ts you have
// stenil.config.ts
export const config: Config = {
globalStyle: "src/global/app.css",
....
}
In the app.css file you can import the variables from node_modules:
/*
* app.css
*/
#import '~design-tokens/dist/tokens.css';
/*
* Some other custom css here
*/
~ here refers to the node_modules folder, so then design_tokens is the package that you have installed in node_modules.
You can also look into using sass for your app.css file instead as described here: https://stenciljs.com/docs/plugins. So you would use the #stencil/sass plugin shown in the link to handle the compiling, and rename your app.css to an app.sass instead. But this shouldn't be necessary if your design tokens are CSS custom properties.

Related

typescript export sub-modules without "dist" folder

I have a simple module modA:
modA/
- package.json
- dist/
- index.js
- db.js
- stuff.js
I'd like to be able to use the submodules "db" and "stuff" like this: import * as db from modA/db -- how can I do that? I have main: dist/index.js in my package.json but that doesn't set dist/ as a default for submodules, so the only way I can get it to work is import * as db from modA/dist/db (explictly including the "dist" in the import). import * as db from modA/db just gives the "Cannot find module" error.
The dist is there because I'm compiling from typescript.
In case it's important, I want this to work in node.js and browser, where I'm using webpack.
As an alternative, can I add some kind of namespace re-export code in index.js to make this work?
In order to make following import work
import * as db from 'modA/db';
In tsconfig.json add paths like below
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"modA/*": [
"dist/*"
]
}
}
}
Ref: https://indepth.dev/configuring-typescript-compiler/

Is there a way in Webpack to extract imported CSS into multiple files?

This is my folder structure:
src/yolo/block.js
src/yolo/editor.scss
src/yolo/style.scss
This is an excerpt of my webpack.config.js
module.exports = {
entry: glob.sync('src/**/block.js'),
output: { path: 'dist' },
plugins: [new MiniCssExtractPlugin()],
...
}
This is what the js file looks like:
block.js
import './editor.scss'
import './style.scss'
I expect the output to be:
dist/yolo/block.js -> es5
dist/yolo/editor.css
dist/yolo/style.css
But instead I get:
dist/yolo/block.js
dist/yolo/block.css
What Webpack does here is to compile all CSS and JS dependencies in 2 files because they are required/imported in the block.js. Importing a file means your code needs them, it would be wrong not to package them with Webpack.
If you want Webpack to compile different CSS/JS in different files you have to create another JS file that will include only one CSS file and remove the appropriate import from block.js.

Cannot import stylesheets from node_modules without tilde (~)

I'm trying to create a simple web app with material-components-vue and vue-cli with webpack, however, I found out that I cannot import stylesheets from node_modules without a preceding ~.
I have tried several webpack/vue-cli configs, and ended up with a config in vue.config.js passing loader options.
My vue.config.js looks like this:
module.exports = {
css: {
loaderOptions: {
sass: {
includePaths: [
'./node_modules', //here I include node_modules
]
},
}
}
}
So I expect to be able to import stuff like so:
#import 'normalize/normalize'
(assuming I have a directory called normalize in my node_modules which contains a file normalize.scss)
However, webpack throws an error, saying it cannot find the module.
But, this does work:
#import '~normalize/normalize'
This wouldn't be a problem if all #imports were written by me, but because I use a third-party module which has #imports inside them, webpack fails to compile.
EDIT 1:
As #Styx asked to
Share more configs, please
and
show the output of vue inspect --rule scss, and the whole file with this problematic import
Here it is:
My problematic file is pretty empty:
<template>
<div id="app">
<m-button>Hello</m-button>
</div>
</template>
<script>
import Vue from 'vue'
import Button from 'material-components-vue/dist/button'
Vue.use(Button)
export default {
name: 'App',
components: {
}
</script>
<style lang="scss">
#import "~material-components-vue/dist/button/styles"; //this works
#import "material-components-vue/dist/button/styles"; //but this does not
</style>
My output from vue inspect --rule scss is located here
All other configs are as generated by vue init webpack <name>
EDIT 2: Exact steps to reproduce this issue:
Initialize a vue-webpack app:
vue init webpack .
Vue build: Runtime + Compiler (Default)
Vue-router: no
Package manager: npm
Then, install sass-loader
npm i -D sass-loader node-sass
Create a file vue.config.js and populate it with the following:
module.exports = {
css: {
loaderOptions: {
sass: {
includePaths: [
'./node_modules', //here I include node_modules
]
},
}
}
}
After that, install a module containing scss/sass
(E.g. for material-components-web, npm i material-components-web)
Then, create an import to a stylesheet located in node_modules, like so:
#import '#material/button/mdc-button'; //mdc-button comes with material-components-web
Finally, start the dev server:
npm run dev
It will throw the following error:
ERROR Failed to compile with 1 errors 11:36:35 AM
error in ./src/App.vue
Module build failed:
#import '#material/button/mdc-button';
^
File to import not found or unreadable: #material/button/mdc-button.
in /home/maxim/projects/holiday.js/stackoverflow/src/App.vue (line 18, column 1)
# ./node_modules/vue-style-loader!./node_modules/css-loader?{"sourceMap":true}!./node_modules/vue-loader/lib/style-compil
er?{"vue":true,"id":"data-v-7ba5bd90","scoped":false,"hasInlineConfig":false}!./node_modules/sass-loader/lib/loader.js?{"s
ourceMap":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/App.vue 4:14-359 13:3-17:5 14:22-367
# ./src/App.vue
# ./src/main.js
# multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/main.js
By the way, in the first example I wanted to import material-components-vue/dist/foo/styles, but here I import #material/foo.
In this configuration your vue.config.js is ignored. This file is used by #vue/cli-service, but you're using webpack-dev-server instead. Thus, your sass-loader doesn't receive this includePaths option.
You can either use modern vue create <app-name> command, or if you want to modify existing project:
Open build/utils.js file.
Find return ... in exports.cssLoaders function:
return {
...
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
...
}
Modify it like this:
const includePaths = [path.resolve(__dirname, '..', 'node_modules')];
return {
...
sass: generateLoaders('sass', { indentedSyntax: true, includePaths }),
scss: generateLoaders('sass', { includePaths }),
...
}
Remove unused vue.config.js file.

How to add a folder as entry in npm package?

I am trying to publish a npm module. Which has a following folder structure.
In my package.json it has "main": "./dist/" I understand this resolve for index.js. But in the dist folder I have individual files named as string.js, class.js, dom.js I am planning to import them as
import { isValidZipCode } from '#scope/utils/string'; but right now I have to import them as import { isValidZipCode } from '#scope/utils/dist/string';
Is there a way I can resolve a folder when I import a module from node_modules?
EDIT: Main idea is to import the files as import { isValidZipCode } from '#scope/utils/string' when I keep individual files for individual exports.
The other answers are correct for the most part, but I think there's one thing that's missing (either from your OG post or from their answers), which is:
Your folder structure is definitely not standard, which likely led to your current problems as well as non-helpful results in the Google searches when you tried to find an answer.
You didn't show your package.json nor your webpack.config.js file contents, which are the key to answering your question even if you did have such a weird file structure.
Some suggestions:
Change your folder structure to be something along the lines of
/
|--src
|--utils
|--string.js
|--[... other js files]
|--index.js
|--dist (will be generated automatically)
|--[config files, like package.json, webpack.config.js, etc]
Make your webpack.config.js have something along the lines of:
output: {
path: path.resolve(__dirname, 'dist'),
//...
}
plugins: [
new CopyWebpackPlugin({
patterns: [
'ReadMe.md', // optional
'package.json',
'LICENSE.md' // optional
]
})
],
In order to fix/normalize the output (e.g. output would be /dist/utils/[string.js, ...], /dist/package.json).
Then, make your package.json main something like
"main": "utils/string.js"
After doing that, your output should look something like
/
|--src
|--utils
|--string.js
|--[... other js files]
|--index.js
|--dist
|--utils
|--string.js
|--[... other js files]
|--index.js // optional: only if you want to support stuff like
// `import { isValidZip } from '#scope/utils';`
|--package.json
|--[config files, like package.json, webpack.config.js, etc]
Finally, you need to cd dist and run npm publish from inside there. (That's why you need the package.json inside that directory.)
I can't really go into details about the #scope portion since I haven't done that myself, but I did the above for one of my own projects and it worked as expected.
All you need to do is to make a index file in root folder then just export all files with the following:
In your dist/string export each method/function on it, and for the index do it follows:
export * from "./dist";
as it helps maintain code and looks cleaner to eye
Regards :)
Create a index file in root folder then just export all files like this
export { default as Str } from "./dist/string";
export { default as Cls } from "./dist/class";
export { default as Dom } from "./dist/dom";
and also update package.json change main from./dis/ to ./
Hope this will help you. Happy coding.

Typescript doesn't resolve modules correctly after compiling to the js

I set the property paths in the tsconfig.json file, like:
"paths": {
"*": [
"*",
"src/*",
"node_modules/*"
],
"src/*": [ "./src/*" ]
},
And it gets me to be able to take some module more easy:
e.g.
- src
|- moduleA
|- utils
|- moduleB
// moduleA
import { something } from 'utils/moduleB'
but after compile I get next path in the moduleB.js:
something = require('utils/moduleB')
instead of relative path:
something = require('./utils/moduleB')
It doesn't work under Node because Node module resolution system knows nothing about utils folder.
So, how can I force tsc to use relative paths here?
Upd:
Here is the real example the one of my resulting js file:
data & utils they are the inner and not externals modules. My question is why tsc doesn't resolve them according to the baseUrl in the compiled files

Categories