How to solve the lit build-in directives import error? - javascript

Using lit 2.5.0 in combination with vite I run into an issue using the lit build-in directives.
Following the docs I added an import to my lit js component like:
import { when } from 'lit/directives/when';
But when I view the resulting site in the browser I always get a missing package error:
Missing "./directives/when" export in "lit" package
Any suggestions on how to fix this import issue?

You need to include the .js extension as well.
import { when } from 'lit/directives/when.js';
This is needed because that's how it's listed in the "exports" of the package which you can see in the package.json file. https://unpkg.com/lit#2.5.0/package.json
"./directives/when.js": {
"types": "./development/directives/when.d.ts",
"default": "./directives/when.js"
},
Rationale for this is to encourage usage of file extensions in import specifiers so as to not require bloated import maps in the browser to support extensionless imports. Described more in detail https://lit.dev/docs/tools/publishing/#include-file-extensions-in-import-specifiers and https://github.com/WICG/import-maps#extension-less-imports.

Related

Webpack doesn't resolve imports of JSON files from D3 packages

I have an Angular app built with Webpack that imports locale JSON files from the d3-format package:
import d3Format from "d3-format/locale/en-US.json";
This worked fine with D3 v5. But after upgrading to v7, I get the following error:
Module not found: Error: Can't resolve 'd3-format/locale/en-US.json'
The JSON file is still in the same location (and in fact the IDE resolves it correctly). But Webpack just doesn't find it when building the app. The main change that broke this import is that the package.json of d3-format now includes this bit (and if I remove it, the build works fine again!):
"exports": {
".": {
"umd": "./dist/d3-format.min.js",
"default": "./src/index.js"
},
"./locale/*": "./locale/*.json"
}
The import also works if I specify an import path like this:
import d3Format from "../../../../node_modules/d3-format/locale/en-US.json";
But this is ugly, I'd rather avoid that.

How to find the reason of "Cannot find module" for nrwl modules?

I use nrwl.io in my project.
I created several libs:
ng g lib rest //ok
ng g lib services //ok
ng g lib models //created ok, but "Cannot find module " later on!
All of these libs were successfully created, but when I try to import my models lib I see error "Cannot find module":
import { ModelA, ModelB } from '#myproj/models'; //Cannot find module '#myproj/models'
The question is: How and where I can check if my '#myproj/models' was properly registered?
P.S. I can see "models" module in nx.json, angular.json and tsconfig.json. And I can see no difference with other modules.
P.P.S. I use "#nrwl/nx": "6.1.0" and "#nrwl/schematics": "6.1.0"
In my case it was because I was dumb and didn't restart my TypeScript server in VS Code:
CMD / CTRL + SHIFT + P
>TypeScript: Restart TS Server
I also had the same issue. Created a library and tried to use it in multiple projects.
First make sure your library is added in main tsconfig.json -> paths property.
"paths": {
"#projectName/LibraryName1": ["libs/LibraryName1/src/index.ts"],
"#projectName/LibraryName2": ["libs/LibraryName2/src/index.ts"],
....
}
Then you must have your project added in your main angular.json file.
"projects": {
"LibraryName1": {
"root": "libs/LibraryName1",
"sourceRoot": "libs/LibraryName1/src",
"projectType": "library",
"prefix": "projectName",
"projectType": "library"
...
}
}
Then obviously check tsconfig.json file for that app in which you are going to use lib. The key is to remove paths property. Because you already added in main tsconfig.json (in my case I used nrwl (a technique for managing multiple apps)).
Now you should be able to reference any of your lib projects like so :
import { class1,class2 } from '#projectName/libraryName1';
Don't forget to export your classes (assuming you have models library ) using index.ts like so :
export * from './lib/class1';
export * from './lib/class2';
Or
If you have any UI library that have components. You should create a module add those components in it and then export it using index.ts
The module file should be in lib folder. e.g
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { NumberOnlyDirective } from './directives/number-only.directive';
#NgModule({
imports: [CommonModule],
declarations: [NumberOnlyDirective],
exports: [NumberOnlyDirective]
})
export class UiModule {}
index.ts file for UI library
export * from './lib/ui.module';
Add UI module's reference in your project app.module.ts
import { UiModule } from '#projectName/LibraryName1';
in imports also
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
NgxPaginationModule,
Ng2OrderModule,
Ng2SearchPipeModule,
AngularEditorModule,
RichTextEditorAllModule,
NgxPrintModule,
DevExpressModule,
UiModule
...
],
I also encountered this issue.
Assume the project is named "project1" and the library is named "libray1" (so we're trying to reference the module "#project1/library1"). Referencing the NRWL NX generated library modules works fine from non-Angular (in my particular case Ionic/Angular) contexts, but caused the "Cannot find module" error from Angular apps within the monorepo.
The problem occurred because the Angular application was looking for the barrel file (index.ts) in the location "project1/libs/library1", whereas NX puts the barrel one level down in "project1/libs/library1/src".
The (slightly annoying) solution is to create an additional index.ts file at the "project1/libs/library1" location with the following content:
export * from './src';
This ensures that the code works from all contexts, and is a fix-once solution (for each new library you generate) as opposed to having to add an explcit reference to the package.json file of each Angular app in the repo.
In case anyone is experiencing this and mentioned solutions didn't help, here's how I fixed it.
After a while I realized that I could import fine in other places, only the app I was trying had the issue
This lead me to check tsconfig of the app
I found that I had set baseUrl: true in tsconfig, which was the reason why the import couldn't be resolved.
TLDR: Remove baseUrl setting from tsconfig.
This is the answer for anyone who integrated nx to an existing monorepo and got this error.
You need to add root tsconfig.base.json to your application tsconfig.json using something like
{
...
"extends": "../../tsconfig.base.json",
....
}
I had the same issue when I was trying to create new lib. I removed the node_modules and reinstall it back. It fixed the issue
While you import something using #model/something, editor will automatically add a full path to the module (in my case). so this is what I had to do to get the import '#' working.
delete the editor added full path import. keep only the one you are typing- ie; with #project/models.
turn the server off and ng serve again.
This is where using --parent-module=apps/myapp/src/app/app.module.ts comes in when creating a lib.
One of the things that flag does is modify the tsconfig.app.json and adds "../../libs/mylib/src/index.ts to the includes which tells TS to use the module.

Using Vue Design System in Nuxt is throwing errors about export in system.js

I am trying to get the components imported into a Nuxt project, following the steps here:
https://github.com/viljamis/vue-design-system/wiki/getting-started#using-design-system-as-an-npm-module
Nuxt does not have a main.js (everything is plugin based), so what I have done is create a "plugin" and then do the import code in there like so (Nuxt recommends this for other libraries too and works fine):
vue-design-system.js
import Vue from 'vue'
import system from 'fp-design-system'
import 'fp-design-system/dist/system/system.css'
Vue.use(system)
Then in my config I do (removed other code in config):
nuxt.config.js
module.exports = {
css: [
{ src: 'fp-design-system/dist/system/system.css', lang: 'css' }
],
plugins: [
{ src: '~plugins/vue-design-system', ssr: true }
]
}
When I run npm run dev in my theme, it builds, but I get a warning:
WARNING Compiled with 1 warnings warning in
./plugins/vue-design-system.js 7:8-14 "export 'default' (imported as
'system') was not found in 'fp-design-system'
Seems to have an issue with the generated system.js regarding the export (the command npm run build:system).
In my page on screen I get the following error when trying to use a component in the design system:
NuxtServerError Cannot find module
'fp-design-system/src/elements/TextStyle' from
'/Users/paranoidandroid/Documents/websites/Nuxt-SSR'
If I hard refresh the page, I then get another message:
NuxtServerError render function or template not defined in component:
anonymous
Any idea what's happening here? It would be really great to get this working somehow.
At this current time, I'm not sure if it's a Nuxt issue or a Vue Design System issue. I think the latter, just because the Nuxt setup I have right now is very bare-bones...so it's not something else causing this.
Thanks.
Repository on GitHub:
Here is the repo for my "theme", but in order to get this going, you will need to create a design system separate from this with the same name and follow the steps to use the design system as a local (file) NPM module.
https://github.com/michaelpumo/Nuxt-SSR
console.log of system (from the JS import statement)
As for your first error (""export 'default' (imported as 'system') was not found in 'fp-design-system'"), the UMD built JS from vue-design-system does not export a "default" object. But you can simply workaround the issue by importing it as:
import * as system from 'fp-design-system'
instead of:
import system from 'fp-design-system'
Then another issue comes quickly as you noticed in your comments: "window is not defined", due again to the UMD built JS that expects window to be globally available, instead of the usual trick to use this (which equals window in a browser). Therefore as it is, the build is not comptible with SSR.
You could however slightly rework the built JS by replacing the first occurrence of window by this, but I am not sure if the result will still work.
Most probably you should better keep this module for client rendering only.
It seems Vue is looking for the ES6 pattern for importing module, which you should use for external javascript modules/files.
in ES6 it is
export default myModule
in ES5 it was
module.exports = myModule
Hope it will help.

Import from subfolder of npm package

I've been working on creating a small library of React components for use in several other projects. I am publishing the package internally (using a private GitHub repository) and then including in another project. However, when I go to import from a subdirectory of the package I am not able to do so as the paths don't match.
The projects using the package all utilize webpack to bundle/transpile code as I am trying to avoid doing any building in the component library if possible.
Directory Structure
- package.json
- src/
- index.js
- Button/
- index.js
- Button.jsx
- ButtonGroup.jsx
- Header/
- index.js
- Header.jsx (default export)
package.json
...
"main": "./src/index.js",
"scripts": "",
...
src/Button/index.js
import Button from './Button';
import ButtonGroup from './ButtonGroup';
export default Button;
export { Button, ButtonGroup};
src/index.js
Is this file actually necessary if only importing from subdirectories?
import Button from './Button';
import ButtonGroup from './Button/ButtonGroup';
import Header from './Header';
export { Button, ButtonGroup, Header };
Other Project
// This project is responsible for building/transpiling after importing
import { Button, ButtonGroup } from 'components-library/Button';
Example
Material-UI is a library of React components that is used by requiring in the following fashion: import { RadioButtonGroup } from 'material-ui/RadioButton. I've tried to figure out how this works for them but to no avail yet.
Similar Questions
How would I import a module within an npm package subfolder with webpack?
This is very nearly the correct approach I require, except that the import path used there involved the src/ directory, which I am trying to avoid (should be component-library/item, not component-library/src/item (which does work currently though))
Publishing Flat NPM Packages
This is exactly what I want except that I was hoping to not have a "build" phase in the package (rely on importing locations to build/transpile)
Questions
Can I skip the src/ directory somehow in the import path?
Can I skip any type of build phase in the package (so developers don't have to build before committing)?
How does a package similar to material-ui handle this?
Can I skip the src/ directory somehow in the import path?
Yes. Using the package.json "exports" field, which should be supported by Webpack in a near future (see this issue), but has already been supported by Node since Node 12 LTS following the Bare Module Specifier Resolution proposal:
package.json
...
"main": "./src/index.js",
"type": "module",
...
"exports": {
"./Button": "./src/Button/index.js",
"./Header": "./src/Header/index.js"
},
...
Now, the following code:
// This project is responsible for building/transpiling after importing
import { Button, ButtonGroup } from 'components-library/Button';
should be translated to:
import { Button, ButtonGroup } from 'components-library/src/Button/index.js';
which should correctly import the requested modules.
Caveat
Now, it would certainly be tempting to try a simpler version like:
...
"exports": {
"./Button": "./src/Button/",
"./Header": "./src/Header/"
},
...
so as the usual import statement
import { ... } from 'components-library/Button';
gets translated to
import { ... } from 'components-library/src/Button';
This looks nice, but it will not work in this case, because your submodules don't have each their own package.json file but rely on their index.js file to be found.
/!\ Unlike in CommonJS, there is no automatic searching for index.js or index.mjs or for file extensions.
src/index.js - Is this file actually necessary if only importing from subdirectories?
I don't think so, but you can keep it if you want.
Can I skip any type of build phase in the package?
Using the "exports" field does not require you to transpile your code.
The answer may depend on how you installed your components library. If you did it via either npm install <git-host>:<git-user>/<repo-name> or npm install <git repo url>,
You should be able to import {Button} from 'component-library/Button' as is, according to your first linked question. Similar to Node's require() resolution, Webpack should resolve subdirectories within component-library relative to component-library's entry point. You can find the docs on customizing the resolution behavior via the webpack.config.resolve property. material-ui seems to rely on resolving subdirectory imports from the module entry directory.
To distribute an ES module library, there's no need for building before distribution. However, projects such as create-react-app may need a pre-transpiled version.
Alternately, you can write import {Button} from 'components-library'.
Webpack will trace the dependencies back through each index without a fuss.
you have to install babel-plugin-module-resolver package
Specify the package relative path in your .babelrc file alias like this
{
"plugins": [
["module-resolver", {
"alias": {
"components-library": "./node_module/components-library"
}
}]
]
}
then you can import subdir of npm package like this
import { Button, ButtonGroup } from 'components-library/Button';
One of the possible solutions there is webpack aliasing system.
You can create another project, call it for example 'app-aliases', so your aliases will be reusable.
This project will has one js file with all of your packages paths:
const path = require('path');
module.exports = {
'#components': path.resolve(__dirname, 'node_modules/components-library/src'),
'#another': path.resolve(__dirname, 'node_modules/any/path/you/want'),
}
And then add it to the webpack configuration in any project which will be responsible for building/transpiling:
webpack.config.js
const appAliases = require('app-aliases');
const config = {
...
resolve: {
alias: {
...appAlises
}
}
}
In the runtime code you will be able to use it like this:
import {Button} from '#components/Button';
import {Something} from '#another'
If you are using typescript you will need to add the same aliases to the paths tsconfig property.
So answers to your questions are:
Yes, you can use any path in aliases
Yes, it is not necessary to build all of your projects
I see that now mui uses imports from directi packages (core for example), see https://material-ui.com/components/radio-buttons/ there is import Radio from '#material-ui/core/Radio';. But I hope they using re-export that I described below.
Also about node.js resolution mechanism.
When you import some library it tries to find node_modules/some-library/package.json and then main property inside it. This property should lead to your main entry point. Usually it is src/index.js (you should set it in package.json if it is no there yet). In this file you can re-export anything you want from internals file structure and will be able to use it without the full path.
Please see this repo for some examples.
I'am an angular developer never used react but what I could tell that material-ui are using monorepo where same concept exists in angular where we create one workspace and this workspace hold multiple project/packages as named in react. for more info Workspaces with Yarn
Material-ui using fake paths in tsconfig to make it appears like src folder doesn't exists this from the git you provided: tsconfig.json
This is possible but requires publishing a curated dist folder rather then the root of your project.
The whole thing is rather simple if you understand how module resolution works, and you just need a small script to prepare your distribution.
Lest I repeat all the details here, please see my answer for Importing from subfolders for a javascript package.

How to load System.js modules with TypeScript?

I'm trying to get TypeScript working with the default Aurelia skeleton, which is based on System.JS as a loader.
I'm having trouble getting TypeScript to accept module imports. I renamed one of the skeleton files, "nav-bar.js" to "nav-bar.ts" to see if I could convert the example into TypeScript. The code results in a compiler error: "Error:(5, 24) TS2307: Cannot find external module 'aurelia-framework'."
import {bindable} from "aurelia-framework";
export class NavBar {
//noinspection ES6Validation
#bindable router = null;
}
How can I get TypeScript to see the aurelia-framework as a valid import? There's a file in the root of the project called config.js that seems to describe the specific location of "aurelia-framework" but TypeScript doesn't know how to load it.
Thanks in advance for your help.
You may want to use d.ts definition files for registration with TypeScript Definitely Typed registry for use with tsd package manager. You can find different implementations on github, for example here or here. Also this tutorial might be useful.

Categories

Resources