How to Export multiple classes in a single library in Javascript? - javascript

I have two JS classes in different files like this:
// Class1.js
export default class Class1 { /* ... */ }
// Class2.js
import Class1 from './Class1'
export default class Class2 { /* ... */ }
And an index.js file that exports both
// index.js
import Class1 from './Class1'
import Class2 from './Class2'
export default {Class1, Class2}
And I'm using webpack to bundle them
// webpack.config.js
const path = require('path')
module.exports = {
devtool: 'source-map',
optimization: {
runtimeChunk: true
},
entry: './src/index.js',
output: {
filename: 'my-lib.js',
path: path.resolve(__dirname, 'dist'),
library: 'MyLib'
},
mode: 'development',
target: 'node',
}
// package.json
{
"name": "my-lib",
"version": "0.1.0",
"main": "dist/my-lib.js",
"module": "src/index.js",
"private": true,
"scripts": {
"build": "webpack"
}
}
However, when I try to use them in a separate project:
// MyComponent.js
import {Class2} from 'my-lib'
I get this warning:
WARN in ./MyComponent.js
"export 'Class2' was not found in 'my-lib'
Why? It's clearly being exported in the index.js file. How can I fix this? Is there even a right way to do this or do I have to create a different library for every class I need?

Related

Move index.html from dir in root dir (vite)

How can i made a move index.html from src/pages/index/index.html to dist/index.html and src/pages/donate/index.html to dist/pages/donate/index.html at a build vite project?
My vite.config.js
import { resolve } from 'path';
import { defineConfig } from 'vite';
const root = resolve(__dirname, 'src');
const outDir = resolve(__dirname, 'dist');
export default defineConfig({
root,
build: {
outDir,
emptyOutDir: true,
rollupOptions: {
input: {
main: resolve(root, 'pages/index/index.html'),
donate: resolve(root, 'pages/donate/index.html')
}
}
}
})
You'll need to use the rollup options in your vite config file.
Something like this should get you going in the right direction:
import { defineConfig } from 'vite';
import { resolve } from 'path';
import path from "path";
export default {
root: path.resolve(__dirname, "src"),
build: {
outDir: path.resolve(__dirname, "dist"),
rollupOptions: {
input: {
index: path.resolve(__dirname, "src/pages/index/index.html"),
donate: path.resolve(__dirname, "src/pages/donate/donate.html"),
},
},
},
};

Rollup + React 17 with new JSX Transform - "React is not defined"

I'm trying to prototype a microfrontend architecture with Rollup and a couple of create-react-app applications. However when I locally yarn link my external app with the container app, I run into the following error:
ReferenceError: React is not defined
23500 | return /#PURE/React.createElement("div", {
| ^ 23501 | id: "container",
23502 | className: "flex flex-col h-screen"
23503 | }, /#PURE/React.createElement(BrowserRouter, null, /#PURE/React.createElement(Header, {
I think it's because we're not importing React at the top of every component/file because of React 17's new JSX Transform allowing you to not have to do that. I'd really like to be able to build our micro frontend package without having to import React in every file, is there a way to do this?
Here is the rollup.config.js:
import babel from 'rollup-plugin-babel';
import commonjs from '#rollup/plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';
import resolve from '#rollup/plugin-node-resolve';
import image from '#rollup/plugin-image';
import visualizer from 'rollup-plugin-visualizer';
import includePaths from 'rollup-plugin-includepaths';
import replace from '#rollup/plugin-replace';
import pkg from './package.json';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
export default {
input: './src/App.jsx',
output: [
{
file: pkg.main,
format: 'cjs',
},
{
file: pkg.module,
format: 'esm',
},
],
plugins: [
external(),
postcss(),
resolve({
mainFields: ['module', 'main', 'jsnext:main', 'browser'],
extensions,
}),
image(),
visualizer(),
includePaths({ paths: ['./'] }),
replace({
'process.env.NODE_ENV': JSON.stringify('development'),
}),
babel({
exclude: 'node_modules/**',
plugins: [
[
'module-resolver',
{
root: ['src'],
},
],
],
presets: ['#babel/preset-react'],
}),
commonjs(),
],
};
In tsconfig.json, add the following code
{
"compilerOptions": {
"jsx": "react-jsx",
}
}
Fixed this by adding { runtime: "automatic" } to the #babel/preset-react preset.
From the preset-react runtime docs:
automatic auto imports the functions that JSX transpiles to. classic does not automatic import anything.
Also mentioned in the React post about the new JSX transform:
Currently, the old transform {"runtime": "classic"} is the default option. To enable the new transform, you can pass {"runtime": "automatic"} as an option to #babel/plugin-transform-react-jsx or #babel/preset-react
Here's a sample:
{
// ...
plugins: [
// ...
babel({
// ...
presets: [
// ...
["#babel/preset-react", { runtime: "automatic" }],
]
})
]
}

Typescript alias import with auto-complete

===== 2021/03/17 Update =====
If anyone still have the same issue. You can try this:
webpack.config.js
module.exports = {
...
resolve: {
alias: {
components: path.resolve(process.cwd(), './src/components'),
},
},
};
tsconfig.json
{
...
"baseUrl": ".",
"path": {
"components/*": ["./src/components/*"]
}
}
===== Origin Post =====
I have a Alert React component below:
import React from 'react';
interface Props {
message: string;
};
const Alert = (props: Props) => {
return (
<div>{props.message}</div>
);
};
export default Alert;
I use the alias import instead of relative import:
// alias import
import Alert from 'components/Alert';
// relative import
// import Alert from '../../components/Alert';
const App = () => {
return (
<div>
<Alert message="I want to know the interface of Alert" />
</div>
);
};
export default App;
If I type "<Alert me" in relative import, VSCode will show the auto-complete options.
However, when I use the alias import, VSCode won't show the auto-complete.
Is there any possible way to let the VSCode knows the 'components/Alert' is '../../components/Alert', and show me the auto-complete that I can understand the interface of Alert's props?
Here is how I setting the alias, I had been tried both webpack config and tsconfig:
webpack.config.js
...
resolve: {
modules: ['node_modules', 'src'],
extensions: ['.ts', '.tsx', '.js', '.jsx'],
mainFields: ['browser', 'jsnext:main', 'main'],
alias: {
'components/*': path.resolve(process.cwd(), 'src/components/*'),
'containers/*': path.resolve(process.cwd(), 'src/containers/*'),
'images/*': path.resolve(process.cwd(), 'src/images/*'),
'hooks/*': path.resolve(process.cwd(), 'src/hooks/*'),
},
}
tsconfig.json
"compilerOptions": {
...
"baseUrl": "src",
"paths": {
"components": ["components"],
"containers": ["containers"],
"images": ["images"],
"hooks": ["hooks"]
}
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
folder structure:
- src
- components
- Alert
- index.tsx
- containers
- App
- index.tsx
You will have to set the baseUrl option as relative to the paths you are aliasing, so if you have alias path set to ./src/components then the baseUrl of that path is ./.
Here is an example:
"baseUrl": "./",
"paths": {
"#components/*": [
"./src/components/*"
],
or
"baseUrl": "./src",
"paths": {
"#components/*": [
"components/*"
],

Compiling TSX to JS with Babel not correct

I'm trying to have babel compile a folder of react tsx files into browser-readable js files in one step. Eveything seems fine, except the compiled JS output still carries the import lines from the tsx files.
I think this is a configuration problem. Here are the key files:
.babelrc
{
"presets": [
[
"#babel/preset-react",
{
"flow": false,
"typescript": true
}
],
[
"#babel/preset-typescript",
{
"isTSX": true,
"allExtensions": true
}
]
],
"plugins": ["#babel/plugin-syntax-class-properties", "react-auto-binding"]
}
tsconfig.json
{
"compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"allowJs": true, /* Allow javascript files to be compiled. */
"outDir": "build", /* Redirect output structure to the directory. */
"rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"jsx": "react",
"noEmit": true,
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
/* Additional Checks */
/* Module Resolution Options */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
/* Advanced Options */
"resolveJsonModule": true /* Include modules imported with '.json' extension */
}
}
The file I'm trying to convert (test.tsx):
import * as React from "react";
import ReactDOM from "react-dom";
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props: any) {
super(props);
this.state = { number: 1 };
}
render() {
return (
<div>
<h1>TESTING</h1>
</div>
);
}
testingTS(something: number) {}
}
const domContainer = document.querySelector("#like_button_container");
ReactDOM.render(<LikeButton />, domContainer);
The babel command
npx babel src --out-dir public/scripts --extensions ".tsx"
The file it output (test.js):
import * as React from "react"; <-- this should not be here ---
import ReactDOM from "react-dom"; <-- this should not be here ---
const e = React.createElement;
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = {
number: 1
};
}
render() {
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", null, "TESTING"));
}
testingTS(something) {}
}
const domContainer = document.querySelector("#like_button_container");
ReactDOM.render( /*#__PURE__*/React.createElement(LikeButton, null), domContainer);
The problem is that you haven't set the correct output format, add #babel/preset-env to tell babel what format it should use

Inversify.js - Reflect.hasOwnMetadata is not a function

I'm trying out Inversify.js for a Typescript application I'm using. Right now, there is no framework involved, so it's pure ES2015.
I'm trying to follow along the example in the main page, but I'm being hit with:
"Reflect.hasOwnMetadata is not a function" when I try to run it in the browser.
I'm using Webpack as package bundler.
Here is my folder structure:
Here is the main app.ts file:
/// <reference path="../typings/index.d.ts" />
/// <reference path="./domain/abstract/match.interface.ts" />
import kernel from "../inversify/inversify.config.ts";
import {symbols} from "../inversify/symbols.ts";
var ninja = kernel.get<INinja>("INinja");
ninja.fight();
ninja.sneak();
interfaces.d.ts:
interface INinja {
fight(): string;
sneak(): string;
}
interface IKatana {
hit(): string;
}
interface IShuriken {
throw();
}
inversify.config.ts
/// <reference path="../node_modules/inversify/type_definitions/inversify/inversify.d.ts" />
/// <reference path="../node_modules/reflect-metadata/reflect-metadata.d.ts" />
/// <reference path="inversify.ts" />
import {Kernel} from "inversify"
//import {MatchHub} from "../app/components/Hubs/match/match-hub.component.ts";
//import {symbols} from "./symbols.ts";
import {Ninja, Katana, Shuriken} from "./inversify.ts";
var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);
export default kernel;
symbols.ts:
export const symbols = {
Match : Symbol("Match")
}
tsconfig.json:
{
"compilerOptions": {
"noImplicitAny": false,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"removeComments": true,
"sourceMap": true,
"target": "es5"
},
"exclude": [
"node_modules",
"bower_components",
"wwwroot"
]
}
Webpack.config.js:
module.exports = {
entry: './app/app.ts',
output: {
filename: '../Scripts/app/app.js'
},
resolve: {
extensions: ['', '.Webpack.js', '.web.js', '.ts','.js', '.tsx']
},
module: {
loaders: [
{
test: /\.ts?$/,
exclude: /(node_modules|bower_components)/,
loader: 'ts-loader'
}
]
},
watch: true
}
Firefox Console Error:
Webpack output:
When I tried to install Inversify the following warnings popped up:
Is it a bug? Or am I doing something wrong? Thanks!
PS: Tried following the sample files, but I couldn't understand anything!
I come from ASP.NET MVC 5 with Ninject so I can relate for most of the syntax.
It seems you will need to include the reflect-metadata package. Try adding an import to it in inversify.config.ts by doing:
import "reflect-metadata";
May be a silly thing to point out, I ran into a the same issue but it was because of the order of imports.
Its unlikely to be the case for any other imports but in case of reflect-metadata it has to be imported before any classes that use it.
import { Container } from "inversify";
//reflect-metadata should be imported
//before any interface or other imports
//also it should be imported only once
//so that a singleton is created.
import "reflect-metadata";
import Battle from "./interfaces/battle";
import EpicBattle from "./interfaces/epic_battle";

Categories

Resources