Webpack requires file extension for react components - reactjs

I'm trying to use Webpack in my React project using VS Code and running into an issue because webpack is now requiring the file extensions for my components.
For example, webpack tells me that it's unable to resolve the following component:
import MyComponent from '../components/Component123';
If I change it to the following by adding the file extension, it works fine:
import MyComponent from '../components/Component123.jsx';
I've never had this before and it's not even the conventional norm. What's causing this and how do I fix it?
BTW, my webpack version is 2.6.1.

Related

Can I use a compiled ReasonReact component together with the CDN version of React? [duplicate]

Building a component with Reason and React always gives me an module import statement for "react", which cannot be found if React is included from a CDN. Is there a solution for this? I've tried to define window.react = React in index.html without success. es6-global setting does not change anything.
I'm not using a bundling program like webpack.
Edit: Possibly relevant thread from Reason forum: https://reasonml.chat/t/can-one-load-reasonml-es6-modules-without-a-bundler/2219
Similar issue (not resolved): can one load reasonml es6 modules without a bundler
importmap (not yet implemented in browsers) could be another solution for this: Using ES6 Modules without a Transpiler/Bundler step
Technically, yes you can, but it's not going to be as easy as going with the npm flow and using a bundler.
The ReasonReact bindings are written in a way that produces output JavaScript that imports modules like:
import * as React from "react";
(If using ES6 module style.)
If using a CDN you would probably want an output that looks like this:
import * as React from "https://some.cdn/react";
The syntax (from the ReasonReact repo) that controls the output JS is:
[#bs.module "react"]
external createElement: (component('props), 'props) => element = "createElement";
If you changed it to:
[#bs.module "https://some.cdn/react"]
external createElement: (component('props), 'props) => element = "createElement";
...then you'd get the desired output. But the problem is then you need to change the sources ... i.e. maintain or find forked bindings for React for that CDN. Or set up some code automation that does a find-and-replace of [#bs.module "react"] with [#bs.module "https://some.cnd/react"]. So either way, it's not as simple as using a bundler.

Can I make Reason+React import react module from CDN?

Building a component with Reason and React always gives me an module import statement for "react", which cannot be found if React is included from a CDN. Is there a solution for this? I've tried to define window.react = React in index.html without success. es6-global setting does not change anything.
I'm not using a bundling program like webpack.
Edit: Possibly relevant thread from Reason forum: https://reasonml.chat/t/can-one-load-reasonml-es6-modules-without-a-bundler/2219
Similar issue (not resolved): can one load reasonml es6 modules without a bundler
importmap (not yet implemented in browsers) could be another solution for this: Using ES6 Modules without a Transpiler/Bundler step
Technically, yes you can, but it's not going to be as easy as going with the npm flow and using a bundler.
The ReasonReact bindings are written in a way that produces output JavaScript that imports modules like:
import * as React from "react";
(If using ES6 module style.)
If using a CDN you would probably want an output that looks like this:
import * as React from "https://some.cdn/react";
The syntax (from the ReasonReact repo) that controls the output JS is:
[#bs.module "react"]
external createElement: (component('props), 'props) => element = "createElement";
If you changed it to:
[#bs.module "https://some.cdn/react"]
external createElement: (component('props), 'props) => element = "createElement";
...then you'd get the desired output. But the problem is then you need to change the sources ... i.e. maintain or find forked bindings for React for that CDN. Or set up some code automation that does a find-and-replace of [#bs.module "react"] with [#bs.module "https://some.cnd/react"]. So either way, it's not as simple as using a bundler.

Typescript cannot load SVG as react components

I'm trying to import in Typescript some SVG icons, but I'm facing some problems.
At the first time I tried to import them, Typescript wasn't able to recognize the file extension.
I solved this issue by creating, as suggested in other Stack Overflow and Github topics, a custom.d.ts file with this rule inside:
declare module "*.svg" {
const content: React.StatelessComponent<React.SVGAttributes<SVGElement>>;
export default content;
}
But the problems seem to not finish here, even if the compilation seems going fine.
The current project I'm working on, is structured this way:
Typescript + React package (with SVG icons files) (SDK)
React Internal Sample page (package) to use the SDK
other internal packages...
For our development phase, we build through Webpack all the packages through different loaders and see the result through the Sample page.
But the final product flow to production is quite different: I export the SDK as CommonJS to an internal NPM Registry so another company can use it in a React project (the equivalent of the Sample page but for production) and push to production the final Webpack bundles with both projects inside.
So, to load in the Sample application the SVG icons, I'm using #svgr/webpack loader, which converts the files.
But when I have to export the SDK through npx tsc, I see that the exported folder, does not contain the folders with svg files.
I've tried to include them in tsconfig.json/files, but got this error:
TS6054: File '<path>/*.svg' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts'.
So, to attempt exporting them I converted my exporting script to use #svgr/cli to export the files to React files from SVGs before compiling to typescript:
// package.json
scripts: {
"build-ts": "rm -rf ./lib; yarn convert-svg-to-react; npx tsc",
"convert-svg-to-react": "npx #svgr/cli -d src src --typescript",
}
In this way, I get the new Typescript files mixed with the SVGs inside the package (so I'll have to remove them later) and I can see them in the exported folder lib.
But watching inside the Typescript exported code, I can see this line (for each svg import):
var close_svg_1 = __importDefault(require("./icons/close.svg"));
Leaving out the Typescript function for Babel __importDefault, you can see that it still requires the file svg, but what I have at this point, are the React components that replaces those files.
During development it works fine because #svgr/webpack loader, resolves the svg files.
But requiring svg files that do not exist, should make the application above it crash.
So, I'm stuck and I need some clues to get out of this situation.
Some clues that I got (but wasn't able to find how to do that), were:
[Best] Find how I can export raw svg files as they are during Typescript compilation without doing that manually, as they are not all in one folder but divided per components areas in the package tree. Doing this, I would tell the other company to add #svgr/webpack to its own building process.
Find how can I tell Typescript to import svg files without specify the extension (currently, removing .svg probably makes it fallback to .ts/tsx and therefore it cannot find the file with that name). In this way, the require would keep requiring the same file name but I could convert SVG to React Components without occurring in problems. But this would also require Typescript to export the file
Otherwise, I should convert all the SVGs in React components and directly use them instead of making them being compiled by #svgr/webpack, but I'm not sure this would have some other side-effects.
Any other clues or any way to achieve the ideas I got? Thank you everybody.

Using own React npm component - appropriate loader issues

I have made a component in my React app that I would like to publish to NPM. It's consists of just one file index.js
import React from 'react'
import PropTypes from 'prop-types';
export default class Test extends React.Component {
//I seem to be getting a specific issue with the lines below
//Do I need a special loader for these?
static displayName = 'Test'
static defaultProps = {
live: true,
}
}
Originally the component was in a components directory of my main app and I include it using:
import Test from './components/Test'
Since then I have created a new folder (not part of my main app) and added a package.json file and the index.js file. I have also published it to NPM which worked fine but when I try to use it after installing...
npm i -S package-name
import Test from 'package-name'
I get an error: You may need an appropriate loader to handle this file type...
My package.json file doesn't have any dependencies or devDependencies at the moment. Do I need to do something with Webpack and Babel?
Do I need to do something with Webpack and Babel?
Most likely. If you are using ES6 syntax in package-name then babel needs to transcode that library as well. When I have encountered that error this has always been the case. I suggest updating your Webpack / Babel configuration to include that library.

React: How Does Importing 'react-addons-{addon}' Work?

For example, to import the test utils:
import ReactTestUtils from 'react-addons-test-utils'
It works, but there is no such module as 'react-addons-test-utils' under node_modules.
And a cursory look at React source code under node_modules reveals that 'react-addons-test-utils' does not exist. In the module root directory there are only react.js and addons.js.
How does this work? What am I missing with my understanding of NPM?
It shouldn't work. Sounds like you may have installed the dependency somewhere globally. I am certain it shouldn't work without the actually package.
BTW, react source code does not actually use react-addons-test-utils:
https://github.com/facebook/react/search?utf8=%E2%9C%93&q=react-addons-test-utils

Resources