I created my react Project A using Create-React-app. Then I bundle it them with Webpack and saved in my Git account.
Now I create another project(Called it Project B)in different directory. Download Project A directly from git. And trying to use it like so:
import React from 'react';
import ReactDOM from 'react-dom';
import { Main } from 'project-A/dist/main'
ReactDOM.render(<Main />, document.getElementById('root'));
I am getting an error like following:
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.
The webpack from Project A looks like this:
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const nodeExternals = require("webpack-node-externals");
module.exports = [
{
/*Client Side*/
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: { minimize: true }
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader,"css-loader"]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./public/index.html",
filename:"./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename:"[id].css"
})
]
}
]
I have research through the github and tried to change the name import, it still does not work.
Project A's component looks like this:
App.js:
render() {
return (
<div>
{this.renderCodeAuthCard()}
{this.renderConfirmCard()}
{this.renderVerifyCard()}
</div>
);
}
export default App;
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
Apparently webpack is not exporting the bundle file that is created in Project A. Since the import yields "undefine".
I am trying to find a way to export my webpack bundle file and use it in another project.
Any help will be appreciated
Its because you are not exporting any thing from index.js of Project A. The libraries installed by npm export functions from index.js.
Related
how are you?
I have a React project with Webpack and Babel, and i'm trying to add Material UI (https://mui.com/) components, however, when i import a MUI component into my project i get the next error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
A workaround i found is to add the ".default" import, but i don't understand why i'm not able to just import it the traditional way.
Here's a test component code that produces the error:
const React = require("react");
const Button = require("#mui/material/Button");
const Navbar = () => {
return <Button variant="contained">Contained</Button>;
};
module.exports = Navbar;
And here's my .babelrc and webpack.config code:
{
"presets": ["#babel/preset-env", "#babel/preset-react"]
}
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
output: {
path: path.join(__dirname, "/dist"),
filename: "index.bundle.js",
},
devServer: {
port: 8443,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: "./src/index.html" }),
new MiniCssExtractPlugin(),
],
};
Does anyone know what i'm doing wrong? I know it might be silly, but i should be able to just import these components the "normal" way as stated in the MUI documentation, instead, i have to import them using the ".default" way.
Thanks in advance, sorry for my bad english.
MUI is designed to be used with EcmaScript modules (ESM) and not CommonJs (CJS). If you do want to use CJS, you can do that, but as ESM and CJS are not 100 % compatible, you will need some workarounds.
To be able to import with CJS syntax with
const Button = require("#mui/material/Button");
MUI would need to export (with CJS) with
module.exports = function Button(props) { ... }
But then the whole export of the Button module is the Button component, and the module could not export anything else.
So instead, everything is exported as named export, and the component itself is exported with the name default.
The ESM import understands the default and you can use the short form, but CJS just imports the javascript object, which is { default: ... }.
A
#mui/material/Button/index.js exports:
export { default } from './Button';
which can be imported with CJS with either:
const Button = require("#mui/material/Button").default;, or
const Button = require("#mui/material/Button/index").default;
B
#mui/material/index.js exports:
export { default as Button } from './Button';
export * from './Button';
which can be imported with CJS with:
const Button = require("#mui/material/index").Button;
( the export * is just "everything from Button", but there is nothing else exported from Button,
except e.g. getButtonUtilityClass from buttonClasses, but we are not interested in that)
I am building a simple form with react, using webpack. I'm new to webpack and react, so there might be an obvious solution, but I just can't figure it out.
My code structure (simplified):
root:
- server.js
- webpack.config.js
- src:
-- App.js
-- index.js
- public:
-- index.html
-- bundle.js
In my app.js is only one Component. I have excluded the ReactDOM.render method into a file index.js. Since i've done that it doesn't work anymore. Before it worked just fine.
The App isn't rendered into my index.html anymore. I guess webpack compiles only my app.js file and ignores my index.js. But I can't know for sure.
When I include the index.js into my App.js everything works just fine.
// /src/App.js
import React, {Component} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
form: 'firmenkontakt'
}
};
render() {
return (
<div className={this.state}>
<form method="post" id={this.state}>
...
</form>
</div>
)
}
}
export default App;
The rendering-file looks as follow:
// /src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('app'));
registerServiceWorker();
I wonder if anything is wrong about my webpack.config.js
// /webpack.config.js
let path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/App.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public')
},
watch: true,
module: {
loaders: [
{
test:/\.js$/,
exclude: /node_module/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-1']
}
}
]
}
}
Your entry file should be src/index.js' and it must importApp.js`
I am working on a React application where in I am having img tag with hard coded image path like below in render function
import '../css/styles.scss';
import React from 'react';
import ReactDom from 'react-dom';
import axios from 'axios';
import { List } from './list';
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="container">
< img src="images/logo.png" alt=""/>
);
}
}
const root = document.getElementById('app-container');
ReactDom.render(<App />, root);
When I run application with webpack-dev-server, application runs fine and I can see image o webpage. However when i run application using webpack command, it generates build folder and and when I run application; I can't see image in webpage.
my webpack.config.js is :
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
resolve(__dirname, 'src', 'js/app.js'),
],
output: {
filename: '[name].[hash].js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
},
{
test: /\.s?css$/,
use: [
'style-loader',
'css-loader?sourceMap&camelCase&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
'sass-loader?sourceMap'
]
}
},
plugins: [
new webpack.NamedModulesPlugin(),
new HtmlWebpackPlugin({
template: resolve(__dirname, 'src', 'index.html')
})
]
}
I understand we can use file-loader in webpack to generate image folder in build folder and use import image from "__path to image"
However is there any way to serve direct image path mention in render function above ?
Thanks in advance
One solution is to use CopyWebpackPlugin. This will copy your images from your src folder to build folder. Then your app can resolve the relative urls.
var CopyWebpackPlugin = require('copy-webpack-plugin');
....
plugins: [
new CopyWebpackPlugin([
{ from: './src/images', to: 'images' },
]),
]
one solution is you have to install url-loader.This is command
npm install --save-dev url-loader
then add following code in webpack.config file in your rules section.
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=25000'
},
next import your image in your APP component.
import logo from 'images/logo.png';
and pass logo in img tag.Like this
< img src={logo} alt=""/>
import '../css/styles.scss';
import React from 'react';
import ReactDom from 'react-dom';
import axios from 'axios';
import { List } from './list';
import logo from 'images/logo.png';
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="container">
< img src={logo} alt=""/>
);
}
}
const root = document.getElementById('app-container');
ReactDom.render(<App />, root);
I have been trying to use Vue.js with TypeScript and I came across this repo.
I faced issues here that I am getting error while importing Vue Single Component File from TypeScript. I am using Visual Studio Code. Please see error below.
main.ts:
// The Vue build version to load with the 'import' command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import * as Vue from 'vue'
import App from './App'
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
VS Code error:
1 ERROR
• main.ts
[ts] Cannot find module './App'. (4 17)
From Alex Jover:
If your editor is yelling at the line import App from './App' in main.js file about not finding the App module, you can add a vue-shim.d.ts file to your project with the following content:
declare module "*.vue" {
import Vue from 'vue'
export default Vue
}
and write :
import App from './App.vue'
instead of
import App from './App'
Check out vue-class-component. Basically, you must add appendTsSuffixTo: [/\.vue$/] to ts-loader's options and esModule: true to vue-loader's options.
// webpack.config.js
{ modules: { rules: [
{
test: /\.ts$/,
exclude: /node_modules|vue\/src/,
loader: "ts-loader",
options: { appendTsSuffixTo: [/\.vue$/] }
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
esModule: true
}
}
]}}
I may have missed something else.
Had this issue even with a vue.d.ts because I had multiple declarations in the same file. Had to split them up like this:
In vue 3 this is the vue.d.ts that has to be somewhere in a path that is included in your tsconfig.json.
// vue.d.ts
declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line #typescript-eslint/no-explicit-any, #typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}
Also I wanted to set global properties on my vue instance and have them available in any component via intellisense. After adding the following code to my vue.d.ts file, the editor complained when I imported .vue files into typescript. So I had to add a separate vue-runtime.d.ts file, or it wouldn't work:
// vue-runtime.d.ts
import '#vue/runtime-core'
declare module '#vue/runtime-core' {
interface ComponentCustomProperties {
customFunction: (val: number) => string;
}
}
Then customFunction will be registered on all components!
When using the vue-cli, adapt vue-loader-conf.js as follows:
var utils = require('./utils')
var config = require('../config')
var isProduction = process.env.NODE_ENV === 'production'
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction, esModule: true
}), esModule: true
}
FYI, you can generate . d.ts file for your components by turn on declaration generate in tsconfig. json, copy them to the source dir, see what you've got!
I just simply want to export and import a child component into my rot-directory (App.js) and render it out in the browser, but I get this error message in terminal "Module not found: Error: Cannot resolve 'file' or 'directory'". I don't understand what I typed wrong or why I cannot import my child to my App.js.
Have tried to solve this problem but with no results. I've been testing this in my "App.js" to get a more explicit name but not working:
import { ContactsList } from './ContactsList';
I've also tried typing this in my "ContactsList.js" but with no result:
export default class ContactsList extends React.Component {}
I'am a beginner so excuse me for my knowledge but I really want to learn this and the power of react. Please help me for better understanding!
--------App.js---------
import React from 'react';
import ReactDOM from 'react-dom';
import ContactsList from './ContactsList';
class App extends React.Component {
render() {
return (
<div>
<h1>Contacts List</h1>
<ContactsList />
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'));
--------ContactsList.js---------
import React from 'react';
import ReactDOM from 'react-dom';
class ContactsList extends React.Component {
render() {
return (
<ul>
<li>Joe 555 555 5555</li>
<li>Marv 555 555 5555</li>
</ul>
)
}
}
export default ContactsList;
--------webpack.config.js---------
module.exports = {
entry: './src/App.js',
output: {
path: __dirname,
filename: 'app.js'
},
module: {
loaders: [{
test:/\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}]
}
};
In your ContactsList.js file, use a <div> to wrap the <ul>
Also in your webpack config file. Can you try to use loader : "babel-loader" instead of loader: 'babel'(Don't forget to install the babel-loader package)
Also remove the query part and try to create a separate .babelrc file with the following settings:
{
"presets" : [
"react",
"es2015"
]
}
Hope this can solve your problem
According to es6 module mechanism the default module should be
imported without {}
import ContactsList from './ContactsList';
and export like
export default class ContactsList extends React.Component {}
But I guess you are trying babel on .jsx extension however it seams
you are using ContactsList.js
Just change the to .jsx to .js in
--webpack.config.js
module.exports = {
entry: './src/App.js',
output: {
path: __dirname,
filename: 'app.js'
},
module: {
loaders: [{
test:/\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}]
}
};
Hope it works
You need to do some changes on webpack.config.js file. first replace
test:/\.jsx?$/,
with
test: /\.(js|jsx)$/,
Secondly import modules as follows
import ContactsList from 'path-of-the-file';
But you need to provide the actual path. to get the path correct there are many plugins available depending on the text editors we use. i am using https://github.com/sagold/FuzzyFilePath