Webpack - import const from .d.ts file not working - Can't resolve '#nuvolo/servicenow-types/server/GlideRecord' - javascript

I'm doing this:
import { GlideRecord } from "#nuvolo/servicenow-types/server/GlideRecord";
I have a file node_modules/#nuvolo/servicenow-types/server/GlideRecord.d.ts
It contains:
...
type GlideRecordConstructor = { new <T>(table: string): GlideRecord<T> };
type GlideRecord<T> = GlideRecordBase<T> & T;
declare const GlideRecord: GlideRecordConstructor;
export { GlideRecord };
If I run tsc it works, no errors
Webpack says:
Module not found: Error: Can't resolve '#nuvolo/servicenow-types/server/GlideRecord' in ...
Webpack config:
{
mode: "production",
//set name of record as the library name
output: {
filename: "file.js"
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
//use: 'awesome-typescript-loader',
exclude: /node_modules/,
},
],
},
resolve: {
//modules: ['node_modules'],
extensions: [ '.ts', '.js' ], // Allows imports to work from .ts and .js
},
}
tsconfig.json:
{
"transpile": false,
"compilerOptions": {
"lib": ["es2015", "dom"],
"esModuleInterop": true,
"baseUrl": ".",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true
}
}
how do I fix this?
I've also created a GH issue here: https://github.com/nuvolo/sincronia/issues/138

Related

`Cannot read properties of undefined` for enum after bundling with webpack

I have a React Library that I want to make buildable using Webpack. The library is written using Typescript. It seems everything is working, but for some reason enums aren't.
When I install the library into my React App, I find Cannot read properties of undefined in the browser console for the enum.
I've tried looking in the outputted bundle and it does appear that the enum is being compiled into the bundle. I feel like I must have a misconfiguration somewhere. Before I was able to bundle with microbundle-crl which we're moving from in favour of Webpack.
Here is my webpack.config.js file:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const DtsBundleWebpack = require('dts-bundle-webpack');
module.exports = {
mode: 'production',
entry: './src/index.tsx',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
resolve: {
extensions: ['.tsx', '.ts', '.json', 'jsx', '.js'],
},
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, //Extract css into files
'css-loader', // Turns css into commonjs
],
},
{
test: /\.pcss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader', // Turns css into commonjs
'postcss-loader'
]
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: 'randomcompany-components.css' }),
new DtsBundleWebpack({
name: '#randomcompany/components',
main: './dist/src/index.d.ts',
out: '../index.d.ts',
}),
],
};
My tsconfig.json is as follows:
{
"compilerOptions": {
"outDir": "dist",
"module": "esnext",
"lib": ["dom", "esnext"],
"types": ["react", "react-scripts"],
"moduleResolution": "node",
"jsx": "react",
"sourceMap": true,
"declaration": true,
"declarationDir": "dist",
"esModuleInterop": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"isolatedModules": true,
"preserveConstEnums": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true
},
"include": ["src", "src/lang"],
"exclude": ["node_modules", "dist", "src/stories"]
}
My enum is in this format:
export enum Test {
TestOne = "Test One",
TestTwo = "Test Two",
TestThree = "Test Three"
};
export default Test;
You should write it like below:
const Test = {
TestOne: "Test One",
TestTwo: "Test Two",
TestThree: "Test Three",
};
export default Test;
But in my opinion, using enum makes your bundle file a little bit heavy, just advise. use simple JavaScript objects.

imported apiService undefined in typescript

We are using typescript and exporting one class as following (we are using nuxt and class style component if this relates to webpack issue).
export class ApiService {
static apiHost = '/';
}
When we try to import it as following, it gives ApiService as undefined and so gives error on apiHost access as ApiService gets undefined.
import { ApiService } from '../services/api-service';
my tsconfig is as following.
{
"compilerOptions": {
"module": "commonjs",
"declaration": false,
"removeComments": true,
"noLib": false,
"allowSyntheticDefaultImports": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowJs": true,
"target": "esnext",
"resolveJsonModule": true,
"sourceMap": true,
"outDir": "./dist",
"esModuleInterop": true,
"moduleResolution": "node",
"baseUrl": "./",
"skipLibCheck": true, // TODO: Remove. Temporary. https://github.com/nuxt/typescript/issues/49
"paths": {
"~/*": ["server/*"],
"#/*": [
"client/*"
],
},
"types": [
"node",
"#types/node",
"#nuxt/vue-app",
"vuex-class-component/dist",
]
},
"include": [
"server/**/*",
"client/**/*"
],
"exclude": [
"node_modules"
]
}
my webpack.config.js
const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const WebpackShellPlugin = require('webpack-shell-plugin');
module.exports = {
entry: ['webpack/hot/poll?1000', './server/main.ts'],
watch: true,
target: 'node',
externals: [
nodeExternals({
allowlist: ['webpack/hot/poll?1000'],
}),
],
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
mode: 'development',
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new WebpackShellPlugin({ onBuildEnd: ['node dist/main.js'] }),
],
output: {
path: `${__dirname}/dist`,
publicPath: '/',
},
};
Command I am running
ts-node -r tsconfig-paths/register server/main.ts
Actually I didn't post entire code as I thought it wasn't necessary.
But service was also calling back the class where service was imported.
import { AuthConfig } from '../config/auth-config';
export class ApiService {
static apiHost = '/';
static mgr = new Oidc.UserManager(
new AuthConfig().IdentityServerOAuth2Config, // This was causing issue as it was causing cyclic imports.
);
}
Follwing is the code where cyclic dependency was happening.
import ApiService from '../services/api-service';
export class AuthConfig {
`${ApiService.apiHost}api/callback` // This was again calling back the apiService resulting in cyclic dependency.
}

Absolute Imports not working with WebPack

I'm trying to setup up absolute imports, but it seems my webpack configs are wrong and the entry point it starts from is relative and not from ./src
I've looked through the webpack docs and they recommend adding an entry point, which I have but still nothing.
Error I get:
Module not found: Error: Can't resolve 'contexts' in '/Users/gurneet/Desktop/Projects/projectfrontend/src/components/Home'
structure:
Project
|- src
| - components
| - Home
| - Featured.tsx
| - contexts
| - index.ts
| - AllDataProvider.tsx
|-package.json
|-tsconfig.json
|-webpack.config.js
// FEATURED.TSX
import React from 'react';
import {useData} from '../../contexts'; // this works
import {useData} from 'contexts'; // this doesn't work.
Even though when I hover over both the imports they points to the say index.ts file that has all the exports.
// WEBPACK
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
devtool: 'source-map',
devServer: {
historyApiFallback: true,
},
entry: './src',
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
{
test: /\.svg/,
use: {
loader: 'svg-url-loader',
options: {
// make all svg images to work in IE
iesafe: true,
},
},
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html',
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'public/_redirects' },
],
}),
],
};
//TSCONFIG
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"baseUrl": "src",
"paths": {
"src/*": ["src/*"]
},
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": false,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
Where am i going wrong?

Webpack + Typscript library import is undefined in React project

I am trying to make a React library using Typescript, Webpack and Babel however I am running into a problem. If I build then import the library into a React project then my import is 'undefined' (See the below error). I think this would be because in the bundle.js there is no module.exports for the variable that would represent my class there is only a __webpack_exports__["default"] = (ExampleComponent); (However I am unsure of what this does in practice so I could be wrong.)
I specifically got this error:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
What I have tried:
Changing the tsconfig target to es6 and module to commonjs
Changing the tsconfig target to es6 and module to esnext
Changing the tsconfig target to es5 and module to esnext
Changing the tsconfig target to esnext and module to esnext
Changing the tsconfig target to es6 and module to es6
Changing the tsconfig target to commonjs and module to es6
Importing the library as 'import * as ExampleComponent from ...' and 'import {ExampleComponent} from ...' (As intended) both times 'ExampleComponent' was undefined.
Versions:
babel-loader: ^8.1.0
Webpack: ^4.43.0
typescript: ^3.8.3
Code:
React Project:
import React from "react";
import { ExampleComponent } from "test-lib";
// This is always undefined
console.log(ExampleComponent);
function App() {
return <ExampleComponent />;
}
export default App;
Library Project:
index.ts:
import ExampleComponent from './ExampleComponent'
export { ExampleComponent }
ExampleComponent.tsx
import * as React from 'react'
import './ExampleComponent.css'
interface Props {
text: string
}
// prettier-ignore
const ExampleComponent: React.FC<Props> = ({ text }) => (
<h1 className="example-text">{text}</h1>
)
export default ExampleComponent
Library Configs:
tsconfig.json:
{
"compilerOptions": {
"outDir": "dist",
"module": "esnext",
"lib": ["dom", "esnext"],
"moduleResolution": "node",
"jsx": "react",
"sourceMap": true,
"declaration": true,
"esModuleInterop": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowSyntheticDefaultImports": true,
"target": "es5",
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src", "tests"],
"exclude": ["node_modules", "dist", "example"]
}
.babelrc:
{
"presets": [
[
"#babel/preset-env",
{
"debug": true,
"useBuiltIns": "usage",
"corejs": 3
}
],
"#babel/preset-react",
"#babel/preset-typescript"
]
}
Webpack Config:
const path = require('path')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
module.exports = {
entry: {
bundle: './src/index.ts',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.json'],
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [{ loader: 'babel-loader' }, { loader: 'ts-loader' }],
},
{
test: /\.css$/,
loaders: ['style-loader', 'css-loader'],
},
{
test: /\.(gif|png|jpe?g|svg)$/,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
disable: true,
},
},
],
},
{
test: /\.js$/,
enforce: 'pre',
loader: 'source-map-loader',
},
],
},
plugins: [new ForkTsCheckerWebpackPlugin()],
}
If you want to see the full code here is a link to the Github Repo.
Based on the comment from Scovy I was able to get this working by using the output.libraryTarget and output.globalObject output options.
Now my output entry in my webpack.base.config.js looks like this:
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
libraryTarget: 'umd',
globalObject: 'this',
},
Update:
The above change did not seam to work 100% of the time so I found a library called esm-webpack-plugin which ended up working perfectly.
So the final code for the output entry in the webpack config is:
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
library: 'LIB',
libraryTarget: 'var',
},
and I also added the plugin:
plugins: [new ForkTsCheckerWebpackPlugin(), new EsmWebpackPlugin()],

Cannot access prototype after compiling with Webpack in Typescritp

I Converted an old Javascript library for the company I work with, to a brand new Typescript Library. I use WebPack since I heard i need a module management system in order to make my library works in the browser. Problem is, whenever i'm trying to initiate my library ( in the JQuery function $(document).ready() , i cannot access my object prototype, I got a typeError :
Uncaught TypeError: Cannot read property 'loadPage' of undefined
Here is my code :
webpack.config.js
const path = require('path');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
var webpack = require("webpack");
var fs = require("fs");
module.exports = {
entry: './src/libraryLoader.ts',
module: {
rules: [
{
test: /\.(tsx?)$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.json$/,
use: {
loader: "file-loader",
options: {
name: "[name].[ext]",
publicPath: "config/"
}
},
exclude: /node_modules/
}
]
},
plugins: [
new CopyWebpackPlugin([
{ from: 'src/settings/config', to: "config" }
]),
new UglifyJsPlugin({
uglifyOptions: {
ie8: true,
//compress: true
}
}),
new webpack.BannerPlugin({
banner: fs.readFileSync('./copyright', 'utf8'),
raw: true
})
],
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
modules: [
"node_modules"
]
},
// Enable sourcemaps for debugging webpack's output.
devtool: "eval",
output: {
filename: 'library.min.js',
path: path.resolve(__dirname, 'dist'),
},
watch: false,
watchOptions: {
ignored: /node_modules/
},
externals: {
// require("jquery") is external and available
// on the global var jQuery
"jquery": "jQuery"
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"moduleResolution": "node",
"module": "commonjs",
"outDir": "build",
"strict": true,
"noImplicitAny": true,
"allowJs": true,
"sourceMap": true,
"typeRoots": [
"./node_modules/#types"
],
"project": "src",
"lib": [ "es2015", "dom"]
},
"include": [
"src/**/*",
"typings/**/*"
]
}
Where I load my library :
$(document).ready(function () {
let loader = new LibraryLoader();
loader.library().loadPage(); // <- Error here
/*...*/
});
My Loader class
export class LibraryLoader{
private _library: Library;
public LibraryLoader() {
this.setLibrary(new Library(/* ... unrelated options ... */));
}
public library(): Library{
return this._library;
}
private setLibrary(value: Library) : void {
this._library = value;
}
}
P.S. There is a loadPage function in the library, but the function library() return undefined anyways,

Categories

Resources