Imported dependency requires another dependency to be first available in scope - javascript

I'm trying to import a library that extends another one, here's my first approach:
import * as PIXI from 'pixi.js';
import 'pixi-layers'; // extends PIXI classes
I get an Uncaught ReferenceError: PIXI is not defined on runtime when pixi-layers tries to Object.assign on a PIXI class.
I suppose this is related to how webpack's hoisting, I've tried to use:
imports-loader
script-loader
I've also tried to provide PIXI through webpack:
module.exports = {
// ...
plugins: [
new webpack.ProvidePlugin({
PIXI: 'pixi.js',
}),
],
};
PIXI remains unavailable to pixi-layers, how can I bundle pixi-layers and make sure it can actually work with the PIXI object?

Turns out providing PIXI as a plugin through the webpack config file was the solution, I just has this same config file compile in the wrong location (paths are hard).

Related

Import ES6 module from http url in Typescript

I am writing an ES6 module which depends on the other ES6 module specified with http url like this:
import { el, mount } from "https://cdnjs.cloudflare.com/ajax/libs/redom/3.26.0/redom.es.js";
const pElem = el("p") // definitely works in Javascript
When I tried to translate my module in Typescript, I got this error:
Cannot find module 'https://cdnjs.cloudflare.com/ajax/libs/redom/3.26.0/redom.es.js' or its corresponding type declarations.
I'm using ts-watch npm module to compile Typescript, and it works fine unless I don't use the import from https://....
I also know that if I tried to import npm module (e.g. import {el} from "redom") it works as well. But what I am writing is a module for web browser, not that of npm. With this reason, using webpack is not an option.
Thanks to #acrazing's comment, I managed to resolve this problem. Here's how:
In a new ts file:
declare module 'https://*'
This mutes the error that Typescript compiler attempts to read type declaration.
If you want to access type declaration as a node dependency, paste this in a new ts file:
declare module 'https://cdnjs.cloudflare.com/ajax/libs/redom/3.26.0/redom.es.js' {
export * from 'redom'
}
and add redom dependency in package.json
"dependencies": {
"redom": "3.26.0",
...
},
Then, type declaration is read from local ./node_modules directory, VSCode recognizes the types as well.
declare module 'https://*' somehow doesn't work for me so I simply ignore it.
// #ts-ignore Import module
import { Foo } from "https://example.com/foo.ts";
// Now you can use Foo (considered any)

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.

AngularJS with Typescript and Webpack managing dependencies

My team is tasked with migrating an AngularJS application to use Webpack as a build system combined with TypeScript. This is all done as a prep to gradually move an application from AngularJS to Angular. (We are following migration guides provided by the Angular team)
Today I ran into an issue with TypeScript's 'Import' statement and I can't seem to find the reason for it. I found a solution, but want to know why this is the case.
In this test run I am having 2 modules in 2 different files. AuthModule and LoginModule . I think their dependency is Circular in that AuthModule -> LoginModule -> AuthModule
//in auth.module.js (this module is loaded before LoginModule)
import {LoginModule} from './login.module'; //is just an exported string
const authModule = angular.module('auth.module', [LoginModule])';
...
//in login.module.js
import {AuthModule} from './auth.module'; //again just an exported string
const LoginModule = angular.module('login.module', [AuthModule]);
...
Those are just 2 small snippets and this built and when viewed in the browser everything was working fine.
However, the moment I converted the files to TypeScript it did not seem to like that circular dependency. The app built in webpack without errors, but bombed in the browser.
To fix it I needed to not 'Import' AuthModule in LoginModule and when providing the dependency to the LoginModule I needed to provide a local string instead of the imported String.
//in login.module.ts (don't import AuthModule)
const LoginModule = angular.module('login.module', ['auth.module']); //just provide the name of the module here as a string
...
This builds and works fine and I am fine with that, but want to understand why. What is the difference between a TypeScript import and a 'webpack' import. My .tsconfig module property is set to CommonJS . Is that why?
From what I understand, when you are importing the LoginModule you are importing an instance of that LoginModule, thus angular.js throw an error. Instead you need to provide a string inside that module declaration, that's why it's working.

materialize-css Uncaught TypeError: Vel is not a function

I'm using webpack as my bundler/loader and I can load materialize css in fine (js/css), but when I try to use the toast, it says
Uncaught TypeError: Vel is not a function
I am including the library in the main index.js file by:
import 'materialize-css/bin/materialize.css'
import 'materialize-css/bin/materialize.js'
Does anyone know why this could be happening? Looking at the bundled source, the js for materialize is there.
Had a same problem & came up with somewhat simpler solution:
Only 2 things are needed to be done:
First: Import following in you root module like app.js
//given you have installed materialize-css with npm/yarn
import "materialize-css";
import 'materialize-css/js/toasts';
Second: if webpack, set following Plugin or get the velocity.min.js as global variable just like you would use jquery:
new webpack.ProvidePlugin({
"$": "jquery",
"jQuery': "jquery",
"Vel": "materialize-css/js/velocity.min.js"
}),
I'm also trying to use materialize-css with webpack and have also run into this issue (albeit not for the same reason). Materialize isn't really built with a module loader in mind, and use global variables. They also bundle dependencies into their script directly in a way you might not want in a webpack-workflow.
I have a setup not exactly the same as you but I'll share it anyways, hoping it will help, my webpack+materialize works like this in a file i've created;
/**
* custom-materialize.js
*/
// a scss file where we include the parts I use.
require('./custom-materialize.scss');
/**
* materialize script includes
* we don't use all the plugins so no need to
* include them in our package.
*/
require('materialize-css/js/initial');
require('materialize-css/js/jquery.easing.1.3');
require('materialize-css/js/animation');
// note: we take these from npm instead.
//require('materialize-css/js/velocity.min');
//require('materialize-css/js/hammer.min');
//require('materialize-css/js/jquery.hammer');
require('materialize-css/js/global');
//require('materialize-css/js/collapsible');
require('materialize-css/js/dropdown');
Then just install Velocity from npm npm install velocity-animate
and point the global Vel materialize use to that package instead in webpack.
new webpack.ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery',
'Vel': 'velocity-animate'
}),
you have to import css and js Files separately in your index.html
you must not import css file in index.js
Make sure that the uglifyJsPlugin is like this.
new webpack.optimize.UglifyJsPlugin({sourceMap: true, mangle: false})
mangle property should be false so that the variable names of your source file doesn't change when you minify.

Using createjs-soundjs in react web app

I would like to use https://www.npmjs.com/package/createjs-soundjs to play sounds on a react web app.
I installed the package normally with npm install createjs-soundjs and it's showing in the packages list. How should I include this to my project, so that I could use it?
I have tried the following:
import React from 'react';
import classNames from 'classnames';
import createjs from 'createjs';
import SoundJS from 'createjs-soundjs'; // this line causes an error
The error message in console: soundjs-0.6.2.min.js:17 Uncaught ReferenceError: createjs is not defined. This error message is very clear, but I have no idea where to start. Am I missing something fundamental?
The SoundJS core bundle is not in the proper CommonJS or ES6 format, it's a bundle that makes strong assumption that it's loaded as a top-level script in the browser. So it first tries to create the global value by assigning it to a property on this (which it assumes to be the window) and then tries to access this global values as just createjs.
So obviously this doesn't work in the module context.
There's a workaround though, the code is for Webpack 2 and based on this comment (which is for Webpack 1):
module: {
rules: [
// ...
{
test: /createjs/,
use: [
'imports-loader?this=>window',
'exports-loader?createjs'
]
},
// ...
]
},
plugins: [
// ...
new webpack.ProvidePlugin({
'createjs': 'createjs',
}),
// ...
],
resolve: {
alias: {
'createjs': path.resolve(__dirname, '../lib/soundjs-0.6.2.combined'),
}
},
The 3rd entry (resolve.alias) maps the imports of createjs to the file I've downloaded and placed into my lib folder (which is not as elegant as using something from npm, but now I'm sure what I get. npm version might work as well).
The first entry (module.rules) tells Webpack to first substitute this with window, and then to take the createjs instance from the global (window) context and make it the module export.
Finally, the 2nd entry (ProvidePlugin) precedes all requests for global createjs (in other modules) with const createjs = require('createjs').

Categories

Resources