I want to build a react component library as a node module to then import it into different projects. But if I try to import a component it just returns an empty object.
button.jsx:
import React, {Component} from 'react'
export class Button extends Component {
render() {
return <button className='btn'>Hello Button comp</button>
}
}
export default Button
index.js
var Button = require('./button/button').default;
module.exports = {
Button: Button
}
webpack.config.js
const Path = require('path');
module.exports = {
resolve: {
extensions: ['.js', '.jsx']
},
entry: {
app: './src/components/index.js'
},
output: {
path: __dirname,
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: [
'es2015',
'react'
]
},
exclude: /node_modules/,
include: [
Path.resolve(__dirname, 'src')
]
},
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: [
'es2015',
'react'
]
},
exclude: /node_modules/,
include: [
Path.resolve(__dirname, 'src')
]
}
]
}
}
Main property in package.json is bundle.js
I figured out that when I import Button in a project it is just an empty object. It seems to me as if webpack doesn't bundle the index file properly. Any ideas what could be wrong here?
A webpack bundle does not expose your exports by default, as it assumes that you're building an app and not a library (which is the far more common use of webpack). You can create a library by configuring output.library and output.libraryTarget.
output: {
path: __dirname,
filename: 'bundle.js',
library: 'yourLibName',
libraryTarget: 'commonjs2'
},
output.libraryTarget is the format of the module, which would also allow you to expose the library as a global variable. commonjs2 is the module format that Node uses. See What is commonjs2? for the difference between commonjs and commonjs2.
Since you're using React, you'll expect that the consumer of the library will have React present as a dependency and therefore you don't want to include it in your bundle. To do that you can define it as an External. This is shown in Authoring Libraries, which walks you through a small example.
Related
I have created a JS file by using webpack export.
I am trying to import main.JS file in react app.
I am not able to import JS file created by webpack. Is this way of importing JS is the right approach in react?
I have tried all the library target option in webpack but none of the target type didnt work
webpack.config.js:
const path = require('path');
module.exports = {
entry: ["#babel/polyfill",'./src/index.js'],
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
libraryTarget: 'commonjs',
libraryExport: 'default',
library: 'API'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
};
main.js export file structure:
exports.API=function(t){..}).default;
react app:
import {API} from "./main.js";
I want to use the webpack export file in react app?
My own modules get included in the build but when using a public node module it does not get included for some reason. Here is the code below.
import helloWorld from "./module";
import Redux from 'redux'
console.log(Redux)
console.log(helloWorld)
when I open the browser Redux is undefined but helloWorld works properly and has my object.
The question is, how can I include redux in my build.
Here is my simple WebPack Config
const path = require('path');
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
]
}
}
Are you sure entity with name Redux exists in redux module.
Try import { createStore } from 'redux' instead. The set up looks fine.
I have a React component that I am trying to import the css.
import './Example.css';
class Example extends Component {
return <div className="example-class">Example</div>
}
My file structure looks like this
build
-index.js
src
-index.js
-Example.css
My webpack.config.js looks like the following.
Currently everything builds, but the css doesnt appear to be getting picked up.
Can anyone see what I would need to do to access my classnames after build?
var path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'index.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
exclude: /(node_modules|bower_components|build)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
},
{
test: /\.css$/,
use: [ 'css-loader' ]
}
]
},
externals: {
'react': 'commonjs react'
}
};
The css-loader only processes the CSS but does not make it available in the browser. You can use style-loader for this, which injects the CSS into a <style> tag. (see also Loading CSS)
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
Another possibility is to extract the CSS with extract-text-webpack-plugin. It will extract the CSS and create a .css file in addition to your JavaScript bundle. You can then include the CSS in your HTML.
You can try this:
import styles from './Example.css';
class Example extends Component {
return <div className={styles.example-class}>Example</div>
}
I started a new Vuetify / Webpack project, and tried to implement vue-router after setting up a project via vue init vuetify/webpack.
I set up the router based on the instructions from this tutorial. After some fiddling, I got it working by changing the way I imported Vue components.
In my router/index.js file:
// works for me
import Main from '../components/Main.vue'
// does NOT work; from the tutorial
import Main from '#/components/Main'
My question is, why do I have to import my Main.vue file relatively and include the .vue extension on the import?
My project structure:
-node_modules/
-public/
-src/
|-components/
||-Main.vue
|-router/
||-index.js
|-App.vue
|main.js
-index.html
-package.json
-webpack.config.js
My webpack.config.js file:
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
resolve: {
alias: {
'public': path.resolve(__dirname, './public')
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
objectAssign: 'Object.assign'
}
},
{
test: /\.styl$/,
loader: ['style-loader', 'css-loader', 'stylus-loader']
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}
You are attempting to load a file from an alias directory named #. But in your webpack config file, you haven't defined that alias.
Also, you are required to specify the .vue extension because you haven't added it to the resolvable extensions in the resolve property in your config object.
In your webpack.config.js file, add a list of extensions to resolve and an alias called # which maps to your src directory:
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
'#': path.resolve(__dirname, './src'),
...
}
...
}
Edit: #evetterdrake informed me that when using vue-cli to set up a project with Vuetify, the resolve config property is positioned after the module property, which is different than when setting up a normal Webpack project.
Be sure to add these config options to the existing resolve property or it will be overwritten and ignored.
i'm developing an application with react.js. My application is growing up. So i had little trouble with imports. For example i have a component named foo i'm using it in many places.
import foo from '../../components/foo';
import foo from '../components/foo';
import foo from '../../../components/foo';
As you can see its dirty, not good. So i searched to fix it and i found a solution with webpack. Also i read that title (Configure Webpack’s modules resolution to avoid nested imports) in this article
I added this code into my webpack.config.js file
modules: [
'node_modules',
path.resolve(__dirname, 'src')
]
So my resolve object looks like this
export default {
resolve: {
modules: [
'node_modules',
path.resolve(__dirname, 'src')
],
extensions: ['*', '.js', '.jsx', '.json']
},
...
After that i am able to use import my foo component in anywhere like this.
import foo from 'components/foo';
Everything is okay so far. But problem shows up in test files.
When i try to test foo component it says
Cannot find module 'components/foo' from 'foo.js'
Example test file.
foo.spec.js
import React from 'react';
import foo from 'components/foo';
describe('(Component) foo', () => {
it('should render foo', () => {
expect(true).toBe(true);
});
});
Here is the first problem. I can not import foo like this.
Note: My test file is not in src folder it is in the test folder.
So i changed the path like this then it worked.
import foo from '../../../src/components/foo';
Tes passed everything is looks fine. But we still have the path problem in test files.
Lets try to import another component in foo component.
foo.js
import bar from 'components/admin/bar';
Here is the second problem. Test file FAILED error message is
Cannot find module 'components/admin/bar' from 'foo.js'
I moved my test file in to my foo.js file. But didn't worked.
Here is my whole webpack.config.js
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import autoprefixer from 'autoprefixer';
import path from 'path';
export default {
resolve: {
modules: [
'node_modules',
path.resolve(__dirname, 'src')
],
extensions: ['*', '.js', '.jsx', '.json']
},
devtool: 'inline-source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
entry: [
// must be first entry to properly set public path
'./src/webpack-public-path',
'webpack-hot-middleware/client?reload=true',
path.resolve(__dirname, 'src/index.js') // Defining path seems necessary for this to work consistently on Windows machines.
],
target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
output: {
path: path.resolve(__dirname, 'dist'), // Note: Physical files are only output by the production build task `npm run build`.
publicPath: '/',
filename: 'bundle.js'
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'), // Tells React to build in either dev or prod modes. https://facebook.github.io/react/downloads.html (See bottom)
__DEV__: true,
//'API_URL': API_URL.dev
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({ // Create HTML file that includes references to bundled CSS and JS.
template: 'src/index.ejs',
minify: {
removeComments: true,
collapseWhitespace: true
},
inject: true
}),
new webpack.LoaderOptionsPlugin({
minimize: false,
debug: true,
noInfo: true, // set to false to see a list of every file being bundled.
options: {
sassLoader: {
includePaths: [path.resolve(__dirname, 'src', 'scss')]
},
context: '/',
postcss: () => [autoprefixer],
}
})
],
module: {
rules: [
{test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel-loader']},
{test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader'},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&mimetype=application/font-woff'
},
{test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'},
{test: /\.(jpe?g|png|gif)$/i, loader: 'file-loader?name=[name].[ext]'},
{test: /\.ico$/, loader: 'file-loader?name=[name].[ext]'},
{
test: /(\.css|\.scss|\.sass)$/,
loaders: ['style-loader', 'css-loader?sourceMap', 'postcss-loader', 'sass-loader?sourceMap']
}
]
}
};
How can i solve?
Thanks for your help.
Webpack is not used during test execution. Since you are using babel the babel-plugin-module-resolver https://github.com/tleunen/babel-plugin-module-resolver should solve the issue:
in your .babelrc file
{
"plugins": [
["module-resolver", {
"root": ["./src"]
}]
]
}
A more cleaner approach would be to create an alias in your .babelrc file and then import from that alias, for instance:
{
"plugins": [
["module-resolver", {
"alias": {
"#app": "./src"
}
}]
]
}
And in your file:
import foo from '#app/components/foo'
That way you have no naming conflicts and your paths are nice and short.
Problem solved after i changed this jest object in package.json file.
"jest": {
"moduleDirectories": [
"node_modules",
"src"
]
...