Unexpected token "<" when importing from third party library into React project - javascript

I am fairly new to React and have no experience with webpack and am struggling with the following issue:
I created a new React application with npx create-react-app (which to my understanding uses webpack under the hood) and installed a third-party library with with npm install. So far so good, I am able to use the library and everything runs as expected.
Unfortunately, the library has some limitations and I would like to tweak one of its functions to suit my needs. The original function looks something like this:
project_root/node_modules/third-party-library/modules/export/tweakableFunction.js:
import {someFunction} from "../utils/configUtils";
export const tweakableFunction = (a, b) => {
return someFunction(a, b);
}
project_root/node_modules/third-party-library/modules/export/index.js:
"use strict";
export {tweakableFunction } from "./tweakableFunction";
In my project, I would like to replicate tweakableFunction and add some functionality to it:
project_root/src/tweakedFunction/tweakedFunction.js:
import {someFunction} from "third-party-library/modules/utils/configUtils";
export const tweakedFunction = (a, b) => {
//... do some stuff the original library can't do ...
return someFunction(a, b);
}
project_root/src/tweakedFunction/index.js:
"use strict";
export {tweakedFunction } from "./tweakedFunction";
Unfortunately, when I run my project I get the following error in project_root/node_modules/third-party-library/modules/some_dir/somefile.js:
SyntaxError: [...] Unexpected token
...
> 21 | someFunction: (props) => <SomeComponent {...props} />,
| ^
...
Do I have to create a webpack / Babel config in my root project for this to work? Is what I am trying to achieve even feasible?

First of all, modifying anything inside node_modules folder is not a good idea, since npm update will overwrite anything you change in there. Also, those changes will be available only in your local instance of a project, you wouldn't be able to use them anywhere else. Consider making a public commit if other people may benefit from your tweak or fork this library into your personal repo and add your changes to said repo.
And the error you are seeing happened because you should wrap return statement with React component in parenthesis.
someFunction: (props) => return (<SomeComponent {...props} />);
If after that error is still popping up, you are trying to use JSX syntax inside common JS file

Because node_modules files won't be handled with babel
Files get compiled with babel while you are importing javascript files, but in create-react-app default WebPack config the node_modules has been excluded, so while you are importing the exact file, an error has been thrown, as the <div> JSX syntax is not native js syntax.
the turn => <Som to => return (<Som is an absolute wrong, while using the former format the component will be returned directly, the return keyword is not required.
but sure one thing, do not edit code in node_modules.

Related

How to use an installed npm package in vscode using .Vue framework?

I have installed a npm package, however i am using the vue framework. The npm package is written in JS, but Vue's syntax is different that JS, even though it is a JS framework. How can i use the package in my vue project?
I have mainly installed the npm package and unsure how to translate what is written in it. i am new to coding and only recently learnt JS and now trying Vue
The Vue syntax is still some standard JS, just with some added sugar, and as such, NPM packages can be imported inside your Vue components <script> tag via a simple import.
For example:
import axios from 'axios';
export default {
...
methods: {
doSomething() {
axios.get(...)
}
}
}
Some packages might expose more defined methods and properties for you to import, in which case you can use what is called "destructuring" in order to import just what you need from the package as opposed to the whole package:
import { method_1, method_3, property_a } from 'myPackage';
export default {
data() {
return {
myComponentProperty: property_a
}
},
...
methods: {
doSomething() {
const a = 'something';
const b = method_1(a);
return b;
}
}
}
Generally speaking, just find your package on https://www.npmjs.com/ and look at the instructions to use it, you'll have some examples on how to import and use it in your project.
Depends of the package you're using, if it's a simple date formater or if it's a whole calendar with baked-in features already.
The first one can be chained/nested into a method as explained here.
The other one is quite harder and more advanced, and will require the usage of methods linked below:
if you want to achieve that in Nuxt (meta-framework mainly used with Vue for SSR): https://stackoverflow.com/a/68485267/8816585
for Vue, I guess this is still the way to go: https://vuejs.org/guide/components/provide-inject.html#inject
This article is a bit old but still relevant as of how to abstract and plug some vanilla JS code to your VueJS instance. I'm sure you can find even more like this one.
Since you're new to JS/Vue, I recommend that you take things easy overall and use only the first type of packages that could be easily integrated.
Overall, get used to the whole ecosystem + way of doing things.
An easy way is sometimes to prefix/suffix your package, for example swiper can also be used thanks to swiper/vue.
You can find a nice list of cool packages here overall: https://github.com/vuejs/awesome-vue

webpack encore fails when importing enum from node_modules

I'm trying to use some enum from a library I made in another project.
The library is made with Vue and typescript, bundled with rollup, the project is made Synfony, and the front with Vue and typescript too, builded with Webpack Encore.
The library is a dependency from my project, so I try to import the enum like this:
import { MyEnum } from 'myLibrary/src/enum/MyEnum';
And the enum looks like this
// node_modules/myLibrary/src/enum/MyEnum.ts
export enum MyEnum {
One = 'one',
Two = 'two',
Three = 'three'
}
But when I build I got this error (with Symfony's Webpack Encore):
ERROR Failed to compile with 1 errors 4:37:05 PM
Error loading ./node_modules/myLibrary/src/enum/MyEnum.ts
FIX To process TypeScript files:
1. Add Encore.enableTypeScriptLoader() to your webpack.config.js file.
I obviously already added enableTypeScriptLoader() in webpack.config.js, and I don't know how to solve this.
If I create the same enum file into my project and import it, it works, but I have to keep it in my library and I don't want to duplicate code. And I import interfaces from the same library the same way, and it works fine.
I tried things that don't work :
export const enum kinda work, but I get the TS2475: 'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment or type query. error, and I have to redeclare the enum in another object to use it in my template :/
export declare enum but still get the Add Encore.enableTypeScriptLoader() error
Any idea how to solve this?
EDIT
I have another error message in my browser that add some information:
Module parse failed: Unexpected token (4:7)
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
> export enum MyEnum {
| One = 'one',
| Two = 'two'
I also test to import the same enum from the same library in a fresh project made with Vue Cli, and I have no error.
I'm pretty sure the issue come from Webpack Encore.
Solution found, some details in this Webpack Encore's issue : https://github.com/symfony/webpack-encore/issues/1060
And here's the fix :
1/ Add allowTsInNodeModules in enableTypeScriptLoader options:
Encore.enableTypeScriptLoader((options) => {
options.allowTsInNodeModules = true;
});
2/ Update rule to change exclude option that excludes node_modules, and exclude node_modules but my own modules (where #myCompany is the folder in node_modules where my own modules are.
Encore.configureLoaderRule('typescript', (rule) => {
rule.exclude = /node_modules\/(?!#myCompany)/;
});
This generates a warning when compiling, but for now it's the only way I found to fix this.

How to test typescript function locally manually in React app?

sorry a rookie question, I am using react and typescript (via create-react-app) and if I have some totally non-UI javascript code (a module I am working on to work with some REST api), something along the lines like this:
src/lib/rest.tsx
export const getUser = async function (
username: string,
) {
let response = await fetch(`http://localhost:3000/api/auth/`, {
username
});
return response;
};
I am wondering how can I test this function locally in a REPL or browsers's dev tools, before putting it into real use. I think I have two difficulties right now:
webpack seems not even packaing this module into the code now, if I open Chrom's dev tools I can see other tsx files but not this one, simply becasue I am not importing this module anywhere I think.
even if it is packaged I dont know how to import this module in a REPL or the dev tool console because first I dont know what is the correct syntax here, Would it be import src/lib/rest.tsx? Also seems I cannot import any module in a REPL because import can only happen inside a module.
The workflow here is just I have written some simple typescript function and I want to run them in a REPL like enviorment so I can make sure they are working before using it anywhere or starting to write unit/integration tests against them.
Thanks!
1 is correct, your new module is not imported and thus not bundled by webpack.
I don't think you could use import syntax in console atm. But there are 2 ways you could try.
Just import your code in one of the bundled file, if you are using dev server, change will be reflected to browser automatically:
import { getUser } from '../../lib/rest';
getUser().then(console.log);
Or attach it to window so you could play with it in console:
import { getUser } from '../../lib/rest';
if (typeof window !== 'undefined') {
window.getUser = getUser;
}

Using Vue Design System in Nuxt is throwing errors about export in system.js

I am trying to get the components imported into a Nuxt project, following the steps here:
https://github.com/viljamis/vue-design-system/wiki/getting-started#using-design-system-as-an-npm-module
Nuxt does not have a main.js (everything is plugin based), so what I have done is create a "plugin" and then do the import code in there like so (Nuxt recommends this for other libraries too and works fine):
vue-design-system.js
import Vue from 'vue'
import system from 'fp-design-system'
import 'fp-design-system/dist/system/system.css'
Vue.use(system)
Then in my config I do (removed other code in config):
nuxt.config.js
module.exports = {
css: [
{ src: 'fp-design-system/dist/system/system.css', lang: 'css' }
],
plugins: [
{ src: '~plugins/vue-design-system', ssr: true }
]
}
When I run npm run dev in my theme, it builds, but I get a warning:
WARNING Compiled with 1 warnings warning in
./plugins/vue-design-system.js 7:8-14 "export 'default' (imported as
'system') was not found in 'fp-design-system'
Seems to have an issue with the generated system.js regarding the export (the command npm run build:system).
In my page on screen I get the following error when trying to use a component in the design system:
NuxtServerError Cannot find module
'fp-design-system/src/elements/TextStyle' from
'/Users/paranoidandroid/Documents/websites/Nuxt-SSR'
If I hard refresh the page, I then get another message:
NuxtServerError render function or template not defined in component:
anonymous
Any idea what's happening here? It would be really great to get this working somehow.
At this current time, I'm not sure if it's a Nuxt issue or a Vue Design System issue. I think the latter, just because the Nuxt setup I have right now is very bare-bones...so it's not something else causing this.
Thanks.
Repository on GitHub:
Here is the repo for my "theme", but in order to get this going, you will need to create a design system separate from this with the same name and follow the steps to use the design system as a local (file) NPM module.
https://github.com/michaelpumo/Nuxt-SSR
console.log of system (from the JS import statement)
As for your first error (""export 'default' (imported as 'system') was not found in 'fp-design-system'"), the UMD built JS from vue-design-system does not export a "default" object. But you can simply workaround the issue by importing it as:
import * as system from 'fp-design-system'
instead of:
import system from 'fp-design-system'
Then another issue comes quickly as you noticed in your comments: "window is not defined", due again to the UMD built JS that expects window to be globally available, instead of the usual trick to use this (which equals window in a browser). Therefore as it is, the build is not comptible with SSR.
You could however slightly rework the built JS by replacing the first occurrence of window by this, but I am not sure if the result will still work.
Most probably you should better keep this module for client rendering only.
It seems Vue is looking for the ES6 pattern for importing module, which you should use for external javascript modules/files.
in ES6 it is
export default myModule
in ES5 it was
module.exports = myModule
Hope it will help.

Import external Javascript libraries installed via npm in Meteor 1.3

I want to use the OpenSeadragon library in my Meteor app. As Meteor 1.3 provides support for npm modules, I have installed it via npm using meteor npm install openseadragon.
But now I am not sure how to user it. The OpenSeadragon docs only provides an example using the script tag.
The meteor docs tell us to use import like import moment from 'moment';. But how do I import openseadragon as I am pretty sure it doesn't use ES6 modules and doesn't export anything.
How can I use it using the npm import without loading the openseadragon.js as global for whole app?
The project's (poorly documented) API page states that
OpenSeadragon will also return an AMD module when required with a loader like Require.js.
Therefore, inside a client script, you can simply
import 'openseadragon'; // load globally
and it should give you the module constructor
Now, depending on what you are using, you may initialize your container from that constructor. For React container, this would look something like this :
import React, { Component } from 'react';
import { Random } from 'meteor/random';
import 'openseadragon'; // OpenSeadragon on global scope
export default class OpenSeedragonComponent extends Component {
constructor(props) {
super(props);
this.state = {
options: {
id: Random.id(), // container unique name
// other options here...
}
};
}
componentDidMount() {
this.initialiseWidgets();
}
componentDidUpdate() {
this.initialiseWidgets();
}
initialiseWidgets() {
this.viewer = OpenSeadragon(this.state.options);
}
render() {
return (
<div id={ this.state.options.id }
width={ this.props.width || '800px' }
height={ this.props.height || '600px' }
>
</div>
);
}
};
Note: at the moment of this writing, you will get an error when loading the .map file. Just ignore it, or open an issue with the project maintainer so he properly integrate the project with Meteor. Perhaps someone will write a react / meteor package wrapper for it...
A JS lib doesn't have to specifically use ES6 export keyword to expose symbols, as a matter of fact npm modules are still using CommonJS module.exports in their vast majority because even though package authors write their code in ES6 they publish them to npm using Babel.
In this specific case, you need to globally import the OpenSeadragon lib using import 'openseadragon'; somewhere in your client/ folder.
Then it will be available on window.OpenSeadragon.
Since the nice Yanick Rochon's answer does not seem to work in your case, note that you should still be able to load your library the "old fashion" way, using the [project_root]/client/compatibility/ special folder.
Any library in that folder will not be loaded in an independent scope by Meteor, but rather loaded "as is" like if it were through a classic <script> tag.
Then your OpenSeadragon object should become available on global scope.
As a side note, if you need simple image navigation and not the OpenSeadragon advanced features, you might be interested in trying Leaflet. It is lighter-weight but very stable and well maintained.

Categories

Resources