I have a vue 3 project, Where I created a custom element. But font-awesome component is not working inside that custom element.
main.ts
import {createApp, defineCustomElement} from 'vue';
import App from './App.vue';
import router from './router.ts';
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome';
import MyElement from './component/MyElement.ce.vue';
const myCustomElement = defineCustomElement(MyElement);
customElements.define(`my-custom-element`, myCustomElement);
const app = createApp(App);
app.use(router);
app.component('font-awesome-icon', FontAwesomeIcon);
app.mount("#app");
App.vue
<template>
<div>
<my-custom-element />
</div>
</template>
<script>
export default {
name:'MainApp'
}
</script>
./component/MyElement.ce.vue
<template>
<div>
<h1>my element should work with icon</h1>
<font-awesome-icon icon="fa-brands fa-twitter" />
</div>
</template>
<script>
import { library } from '#fortawesome/fontawesome-svg-core';
import { faTwitter } from '#fortawesome/free-brands-svg-icons';
library.add(faTwitter);
export default {
name: "MyElement",
}
</script>
<style>
h1{
color: red;
}
</style>
webpack.config.js
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.resolve(__dirname, './src/main.ts'),
output: {
path: path.resolve(__dirname, './dist'),
},
devServer: {
hot: true,
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.join('./', 'index.html') },
],
},
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options:{
compilerOptions:{
isCustomElement: (tag) => tag.includes('-')
}
}
},
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/]
}
},
{
test: /\.css$/i,
use: ["css-loader"],
},
]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './index.html'),
inject: 'body',
}),
]
}
package.json
{
"dependencies": {
"#fortawesome/fontawesome-svg-core": "^6.2.1",
"#fortawesome/free-brands-svg-icons": "^6.2.1",
"#fortawesome/free-regular-svg-icons": "^6.2.1",
"#fortawesome/free-solid-svg-icons": "^6.2.1",
"#fortawesome/vue-fontawesome": "^3.0.2",
"#vue/compiler-sfc": "^3.2.41",
"fine-uploader": "^5.16.2",
"fine-uploader-wrappers": "^1.0.1",
"html-webpack-plugin": "^5.5.0",
"ts-loader": "^9.4.1",
"typescript": "^4.8.4",
"vue": "^3.2.41",
"vue-loader": "^17.0.0",
"vue-router": "^4.1.6",
"webpack": "^5.74.0",
"webpack-dev-server": "^4.11.1"
},
"devDependencies": {
"css-loader": "^6.7.2",
"webpack-cli": "^4.10.0"
},
"scripts": {
"start": "webpack-dev-server --mode development"
}
}
Everything works including the style but FontAwesomeIcon is not working as it is supposed to.
This is what it shows in the browser
Can anyone point me in the right direction? Any help would be appreciated.
checkout if your icon available in fontawesome version 6.2.1
Turns out there is an npm package vue3-webcomponent-wrapper. I implemented it and used i tag of font-awesome which solved my issue. I don't know if this is the perfect solution but this is the only solution I found.
Related
My goal:
I am creating a React component library in JavaScript with Webpack 5 and Babel 7 that is published to npm. I want consumers to import individual components into their React apps. I also want to add a development server for stakeholders to add components to the component library.
When running the app locally with 'npm run build && npm run serve' (npx webpack serve) I keep getting this error message:
ERROR in ./src/index.js 20:2
Module parse failed: Unexpected token (20:2)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| root.render(
> <App />
| );
Here is my setup:
./webpack.config.common.js
const path = require('path');
module.exports = {
entry: {
index: './src/index.js',
MyCoolButton: './src/components/buttons/MyCoolButton',
RandomButton: './src/components/buttons/RandomButton',
StyledButton: './src/components/buttons/StyledButton',
theme: './src/tokens/Theme'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
runtimeChunk: 'single',
},
resolve: {
alias: {
path: path.resolve(__dirname, 'src')
},
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
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",
],
},
{
// The test property identifies which file or files should be transformed
test: /\.(js|jsx)$/,
resolve: {
extensions: [".js", ".jsx"]
},
exclude: /[\\/]node_modules[\\/]/,
// The use property indicates which loader should be used to do the transforming.
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
},
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
],
},
};
./webpack.config.prod.js
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.config.common');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = merge(commonConfig, {
mode: 'production',
// do not include source maps on prod build
// devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// Load css to separate file
MiniCssExtractPlugin.loader,
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
],
},
optimization: {
// minimize: true,
minimizer: [
// For webpack#5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`,
new CssMinimizerPlugin({
test: /\.foo\.css$/i,
}),
new TerserPlugin({
terserOptions: {
parse: {
// We want terser to parse ecma 8 code. However, we don't want it
// to apply minification steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the `compress` and `output`
ecma: 8,
},
compress: {
ecma: 5,
inline: 2,
},
mangle: {
// Find work around for Safari 10+
safari10: true,
},
output: {
ecma: 5,
comments: false,
}
},
// Use multi-process parallel running to improve the build speed
parallel: true,
}),
],
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: 'styles.[contenthash].css',
})
],
// As you publish your code as React component, apart from set React as peer dependency you have to set the react as externals to use the react at the consumer library.
externals: {
'react': {
commonjs: 'react',
commonjs2: 'react',
amd: 'React',
root: 'React'
},
'react-dom': {
commonjs: 'react-dom',
commonjs2: 'react-dom',
amd: 'ReactDOM',
root: 'ReactDOM'
}
},
});
./babel.config.js
{
"plugins": [
"babel-plugin-module-resolver"
],
"presets": [
["#babel/preset-env"], // instead of "#babel/preset-es2015",
["#babel/preset-react"]
]
}
./src/index.js
export {default as MyCoolButton} from './components/buttons/MyCoolButton';
export {default as RandomButton} from './components/buttons/RandomButton';
export {default as StyledButton} from './components/buttons/StyledButton';
export {theme} from './tokens/Theme';
import './tokens/theme.scss'; // need import to generate minified css flat file
// kitchen sink for component development
import React from "react";
import { createRoot } from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('app');
const root = createRoot(rootElement);
root.render(
<App />
);
App.jsx
import React, { Component } from 'react';
import StyledButton from "./components/buttons/StyledButton";
import RandomButton from "./components/buttons/RandomButton";
class App extends Component {
render() {
return (
<div>
<div className='container body'>
<div className='row'>
<div className='col-12 text-center mb-4 mt-4'>
<h1>Welcome to the Kitchen Sink Page</h1>
</div>
<div className='col-6'>
<RandomButton />
</div>
<div className='col-6'>
<StyledButton />
</div>
</div>
</div>
</div>
);
}
}
export default App;
and my package.json
...
"peerDependencies": {
"prop-types": "^15.6.0",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"babel-core": "^6.0.0",
"webpack": "^4.0.0"
},
"devDependencies": {
"#babel/cli": "^7.17.0",
"#babel/core": "^7.17.2",
"#babel/preset-env": "^7.16.11",
"#babel/preset-react": "^7.16.7",
"#semantic-release/changelog": "^6.0.1",
"#semantic-release/commit-analyzer": "^9.0.2",
"#semantic-release/git": "^10.0.1",
"#semantic-release/npm": "^9.0.0",
"#semantic-release/release-notes-generator": "^10.0.3",
"#testing-library/react": "^12.1.2",
"babel-core": "^7.0.0-bridge.0",
"babel-loader": "^7.1.5",
"babel-plugin-module-resolver": "^4.1.0",
"commitizen": "^4.2.4",
"css-loader": "^6.6.0",
"css-minimizer-webpack-plugin": "^3.4.1",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.8.0",
"eslint-plugin-jest": "^26.1.0",
"eslint-plugin-react": "^7.28.0",
"jest": "^27.5.0",
"path": "^0.12.7",
"prop-types": "^15.6.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"sass": "^1.49.7",
"sass-loader": "^12.4.0",
"semantic-release": "^19.0.2",
"style-loader": "^1.3.0",
"styled-components": "^5.3.3",
"webpack": "^5.68.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4"
},
"dependencies": {
"babel-plugin-styled-components": "^2.0.2",
"babel-preset-react": "^6.24.1",
"clean-webpack-plugin": "^4.0.0",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.5.3",
"optimize-css-assets-webpack-plugin": "^6.0.1",
"terser-webpack-plugin": "^5.3.1",
"webpack-merge": "^5.8.0"
},
...
I have browsed countless stackoverflow posts and answers, blog posts and I am having a hard time debugging this 'unexpected token' error.
I am new to Webpack so if anyone can see if I am doing something wrong in the Webpack config files, in way the React app is being bundled, or by loading Babel loaders, I would really appreciate some pointers.
how do I write my config, so I can run successfully?
I do not know what's wrong with my webpack.config.js
or wrong code in other files?
can someone tell me what's wrong with my code?
webpack.config.js
var path = require('path');
module.exports = {
entry: './project/frontend/src/index.js',
output: {
path: path.join(__dirname, 'project/frontend/static/frontend/'),
filename: 'main.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
],
rules:[
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
]
},
resolve: {
extensions: ['.js', '.jsx', '.css'],
}
};
package.json
{
"name": "django-drf-react-quickstart",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.4.4",
"#babel/preset-env": "^7.4.4",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.6",
"babel-plugin-transform-class-properties": "^6.24.1",
"weak-key": "^1.0.1",
"webpack": "^4.32.0",
"webpack-cli": "^3.3.2"
},
"dependencies": {
"bootstrap": "^4.3.1",
"css-loader": "^2.1.1",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-bootstrap": "^1.0.0-beta.9",
"react-dom": "^16.8.6",
"reactstrap": "^8.0.0",
"style-loader": "^0.23.1"
}
}
index.js
import '!style-loader!css-loader!bootstrap/dist/css/bootstrap.css';
import App from "./components/app";
app.js
import React, { Fragment, Component } from "react";
import ReactDOM from "react-dom";
import DataProvider from "./DataProvider";
import Table from "./Table";
import Form from "./Form";
import { Button } from 'reactstrap';
class App extends Component {
constructor (props) {
super(props);
}
render () {
console.log('----- in App render -----')
return(
<Fragment>
<DataProvider
endpoint="api/lead/"
render={data => <Table data={data} />} />
<Form endpoint="api/lead/" />
<Button color='danger'>Danger!</Button>
</Fragment>
);
}
}
const wrapper = document.getElementById("app");
wrapper ? ReactDOM.render(<App />, wrapper) : null;
the error messages when i npm run dev
ERROR in ./project/frontend/src/components/app.js 18:6
Module parse failed: Unexpected token (18:6)
You may need an appropriate loader to handle this file type.
| console.log('----- in App render -----')
| return(
> <Fragment>
| <DataProvider
| endpoint="api/lead/"
# ./project/frontend/src/index.js 2:0-35
I do not know what's wrong with my webpack.config.js
or wrong code in other files?
I'm trying to migrate my app to webpack 4. My head hurts already.
Dynamic imports - this is my method of code splitting (page by page). But I can't get it to work. Have set up very simple tester with following packages:
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.11",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.4.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"webpack": "^4.12.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
}
Here is my main test app:
import React from "react";
import ReactDOM from "react-dom";
import style from "./main.css";
import pageLoader from './pageLoader';
class App extends React.Component {
render() {
let page = pageLoader();
return (
<div>
<p>React here!</p>
{page}
</div>
);
}
};
export default App;
ReactDOM.render(<App />, document.getElementById("app"));
and my page I want to load dynamically with separate bundle.
import React from "react";
import ReactDOM from "react-dom";
import style from "./main.css";
const Page1 = () => {
return (
<div>
<p>Page1 here!</p>
</div>
);
};
export default Page1;
Here's my webpack.config so far:
const path = require('path');
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
polyfill: 'babel-polyfill',
app: './src/index.js'
},
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js', //name of non-entry chunk files
path: path.resolve(__dirname, 'dist')
},
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: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
Now here's the part that errors on build. Here's the function which calls the dynamic import:
function pageLoader() {
return import(/* webpackChunkName: "page1" */ './Page1')
.then(page => {
return page.default;
});
}
export default pageLoader;
I get this error on build:
ERROR in ./src/test/pageLoader.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: Unexpected token (2:8)
1 | function pageLoader() {
> 2 | return import(/* webpackChunkName: "page1" */ './Page1')
| ^
3 | .then(page => {
4 | return page;
5 | });
Everything I have read says this is the way to set this up. What am I doing wrong?
I was facing the same issue the fix was:
npm install --save-dev #babel/plugin-syntax-dynamic-import
add following line to .babelrc
"plugins": ["#babel/plugin-syntax-dynamic-import"],
Sources:
https://webpack.js.org/guides/code-splitting/#dynamic-imports
https://babeljs.io/docs/plugins/syntax-dynamic-import/#installation
Just an update for those going down this path: If you are using React, I would recommend react-loadable, makes it extremely easy to do dynamic imports on a per-component basis... a lot of large companies use it.
This my webpack.config file
import webpack from 'webpack'
import path from 'path'
export default {
devtool: 'inline-source-map',
entry: [
path.resolve(__dirname, 'src/index.js')
],
target: 'web',
output: {
path: path.resolve(__dirname, 'src'),
publicPath: '/',
filename: 'bundle.js'
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
loaders: [{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}]
}
};
This is my package.json file
{
"name": "zresume",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon server/server.js --exec babel-node"
},
"author": "",
"license": "ISC",
"dependencies": {
"bootstrap": "^3.3.7",
"d3": "^4.10.2",
"express": "^4.15.4",
"nodemon": "^1.12.0",
"path": "^0.12.7",
"react": "^15.6.1",
"react-bootstrap": "^0.31.3",
"react-dom": "^15.6.1",
"react-router": "^4.2.0",
"redux": "^3.7.2"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-react-hmre": "^1.1.1",
"open": "0.0.5",
"webpack": "^3.6.0",
"webpack-dev-middleware": "^1.12.0"
},
"babel": {
"presets": [
"es2015"
],
"env": {
"presets": [
"react-hmre"
]
}
}
}
My index.js file
import React from 'react';
import ReactDOM from 'react-dom';
import LoginPage from './components/LoginPage';
class App extends React.Component {
render(){
return(
<div>
<h1>El Juego Lindo</h1>
<div>
<LoginPage />
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
LoginPage Component
import React from 'react';
import { Button, Collapse } from 'react-bootstrap';
import LoginForm from './LoginForm';
class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
onButtonClicked: false
}
this.onButtonClick = this.onButtonClick.bind(this);
}
onButtonClick() {
this.setState({
onButtonClicked: !this.state.onButtonClicked
});
}
render() {
return (
<div>
<div> I love football!!!! </div>
<Button className="footballButton" onClick={this.onButtonClick} bsStyle="primary" bsSize="large" block>Football Lover</Button>
<Collapse in={this.state.onButtonClicked}>
<div>
<LoginForm />
</div>
</Collapse>
</div>
);
}
}
export default LoginPage;
enter image description here
Hi guys I'm a pretty novice programmer, and I'm having trouble with my react components rendering. For some reason it is saying that it can't find the module. Can anyone guide me in the right direction?
You should name your files ".js", not ".jsx"
If you must use ".jsx", you need to specify the file ending when importing:
import LoginPage from './components/LoginPage.jsx'
Otherwise, Webpack assumes you've used ".js"
There is an issue with Webpack 3 and you have to add a blank space to the accepted extensions, like this.
resolve: {
extensions: [' ', '.js', '.jsx']
but also i recommend to add an alias to avoid import your components with the . (dot), and also remove the previous workaround
resolve: {
extensions: ['.js', '.jsx'],
alias: {
'Components': path.resolve(__dirname, '/components')
}
}
Now you can import your Components like this
import YourComponent from 'Components/Login'
https://github.com/webpack/webpack/issues/981
Also doble check that babel-node has some issues with ES6 module autoloading https://babeljs.io/docs/usage/cli/#babel-node
I'm getting an error Error: Cannot resolve module 'react' (and react-dom) with webpack. This has to be the hardest project setup I've had to deal with and I'm really not sure why its not working. I've also checked for similar issues on so, and can't seem to find a solution.
webpack.config.js
module.exports = {
entry: './static/js/base/base.jsx',
output: {
path: __dirname + '/static/scripts',
filename: 'bundle.js'
},
resolve: {
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
cacheDirectory: true,
presets: ['react', 'es2015']
}
}
]
}
}
base.jsx
import React from 'react';
import ReactDOM from 'react-dom';
class Navigation extends React.Component {
// ...
constructor(props) {
super(props);
[
// Functions & Event Handlers declaration
].forEach(method => { this[method] = this[method].bind(this); });
this.state = {
hello: 'Hello World!',
};
}
render() {
return (
<div>
<div href="#" class="header item">
WINPMP Login
</div>
<div class="right menu">
<a class="ui primary button item">Students</a>
<a class="ui button item">Teachers</a>
</div>
</div>
);
}
}
React.render(<Navigation/>, document.getElementById('nav'));
I've run npm install, everything is there. Why won't it import properly? How can I make this work?
And my package.json
"devDependencies": {
"babel": "^6.5.2",
"babel-core": "^6.11.4",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1",
"bower": "^1.7.9",
"react": "^15.2.1",
"react-dom": "^15.2.1",
"webpack": "^1.13.1",
"webpack-dev-server": "^1.14.1"
}
Try creating a .babelrc file in your project root which looks like this:
{
presets: [
"es2015", "react"
]
}
and pull out the 'query' field from your webpack config 'loader'