Webpack module source code - javascript

I need to save the code of a es6 code module and dump it.
So ideally what I would need is something like:
import React, {PropTypes} from 'react';
// this function get the source code of the
// module I am running in
function getMyModuleSourceCode = {
...
}
class DemoComponent extends React.Component {
render() {
const myCode = getMyModuleSourceCode();
processMySourceCode(myCode);
}
}

If the module is in a different file, you can import twice, once normally to run code, once with the raw-loader to just pull in the file verbatim.
import module from './module'; //compiled code
import moduleSource from '!!raw!./module'; //source as text
The !! is necessary to override the existing loaders if you are just testing for .js extensions.

You could use the file-loader in webpack and then require whatever file you need in your function:
import React, {PropTypes} from 'react';
// this function get the source code of the
// module I am running in
function getMyModuleSourceCode = {
return require('!!file!./path/to/module.js');
}
class DemoComponent extends React.Component {
render() {
const myCode = getMyModuleSourceCode();
processMySourceCode(myCode);
}
}

Related

Webpack loader for .md file import for "react-markdown" npm library?

When i import a .md file , it gave me error, saying that it cannot read this particular .md file syntax,
I know there needs to be some kind of loader for it to parse the import, but when i looked online there was a loader called 'markdown-loader' which was only for marked npm package.
I am using react-markdown package to read md files
/* eslint-disable react/prefer-stateless-function */
import React, { Component } from 'react';
import ReactMarkdown from 'react-markdown';
import AppMarkdown from './posts/sample.md';
// import PropTypes from 'prop-types';
class CardDetails extends Component {
constructor() {
super();
this.state = { markdown: '' };
}
componentDidMount() {
// Get the contents from the Markdown file and put them in the React state, so we can reference it in render() below.
fetch(AppMarkdown)
.then(res => res.text())
.then(text => this.setState({ markdown: text }));
}
render() {
const { markdown } = this.state;
return <ReactMarkdown source={markdown} />;
}
}
CardDetails.propTypes = {};
export default CardDetails;
here's my markdown content sample.md
# React & Markdown App
- Benefits of using React... but...
- Write layout in Markdown!
i could not find package , i looked everywhere, do you know about the loader ?
Thankyou
Try to use raw-loader:
module.exports = {
module: {
rules: [
{
test: /\.md$/,
use: 'raw-loader'
}
]
}
}

Asset.fromModule is not a function. (In 'Asset.fromModule(image)', 'Asset.fromModule' is undefined)

After updating to Expo sdk 34, I am getting this error:
TypeError: Asset.fromModule is not a function. (In 'Asset.fromModule(image)', 'Asset.fromModule' is undefined).
I have ran the cod-mod which Expo recommends using this command: npx expo-codemod sdk33-imports src when updating to new versions, and I've also tried changing import * as Asset from 'expo-asset'; to import { Asset } from 'expo-asset', but neither of these changes have fixed this warning.
This is my App.js
import React from 'react';
import { Dimensions, Alert } from 'react-native';
import {Root} from 'native-base';
import {createRootNavigator} from './router';
import {configureFontAwesomePro} from "react-native-fontawesome-pro";
import Geocoder from 'react-native-geocoding';
import { AppLoading } from 'expo';
import * as Asset from 'expo-asset';
import * as Font from 'expo-font';
import Api from './services/api';
import Moment from 'moment';
import Config from './config/config';
import './i18n';
import store from './store/store';
import i18n from 'i18n-js';
configureFontAwesomePro();
const RootNav = createRootNavigator();
function cacheImages(images) {
return images.map(image => {
if (typeof image === 'string') {
return Image.prefetch(image);
} else {
return Asset.fromModule(image).downloadAsync();
}
});
}
function cacheFonts(fonts) {
return fonts.map(font => Font.loadAsync(font));
}
export default class App extends React.Component {
constructor() {
super();
this.state = {
isReady: false
};
}
async _loadAssetsAsync() {
const imageAssets = cacheImages([
require('./assets/images/splash.png'),
require('./assets/images/splash-logo.png'),
require('./assets/images/hotdrink.png'),
require('./assets/images/insta.png'),
require('./assets/images/twitter.png'),
require('./assets/images/facebook.png'),
require('./assets/images/yelp.png'),
]);
store.updatePrefix(Expo.Linking.makeUrl('/'));
const fontAssets = cacheFonts(
[{
Roboto: require("native-base/Fonts/Roboto.ttf"),
Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),
Ionicons: require("#expo/vector-icons")
}]
);
await Promise.all([...imageAssets, ...fontAssets]);
}
render() {
if (!this.state.isReady) {
return (<AppLoading
startAsync={this._loadAssetsAsync}
onFinish={() => this.setState({isReady: true})}
onError={(error) => console.log('app js: ', error)}
/>)
}
return (
<Root>
<RootNav uriPrefix={store.prefix} />
</Root>
)
}
}
Geocoder.init(Config.google_maps_key);
Edit:
After making the changes suggested below:
- changing the import of asset from import * as Asset from 'expo-asset'; to import { Asset } from 'expo-asset';
- I am now getting this error, which is slightly different than the one
I originally wrote about
- TypeError: asset.downloadAsync is not a function. (In 'asset.downloadAsync()', 'asset.downloadAsync' is undefined).
Seems like this should just be import { Asset } from "expo-asset"; instead of import * as Asset from 'expo-asset';.
I figured this out since that import statement looked odd, so I copied your App.js into a fresh create-react-native-app install, added a few of the dependencies and commented out the bits that seemed unrelated or references to files that aren't posted here. I got the TypeError: Asset.fromModule is not a function. (In 'Asset.fromModule(image)', 'Asset.fromModule' is undefined) warning, changed the import line, and the app loaded (it didn't do much, but with so much commented out that was expected).
The import statement is pretty easy to accidentally get wrong without actually generating an errors on the import line, may be worth refreshing on how as works when using it, see the docs on MDN
Run this in your root folder:
expo install expo-asset
And then run
expo start -c
just to be sure.

how to import a class in code splitting using import()?

I cannot find out how to import a class in my React app after using the code splitting.
Before (it works!):
import React, {PureComponent} from 'react';
import Tus from './components/test';
class Shopper extends PureComponent {
constructor (props) {
super(props); }
uploadModal () {
/* some function code... */
.use(Tus, {
endpoint: 'http://192.168.22.124:3000/upload/'
})
/* more codes... */
}
After using code splitting (does not work):
import React, {PureComponent} from 'react';
class Shopper extends PureComponent {
constructor (props) {
super(props); }
uploadModal () {
/* some function code... */
.use(import('./components/test').then(Tus => Tus, {
endpoint: 'http://192.168.22.124:3000/upload/'
})
/* more codes... */
}
I am getting this error after using code split
TypeError: Expected a plugin class, but got object. Please verify that
the plugin was imported and spelled correctly.
When I console.log
import('./component/test').then(Tus => console.log(Tus))
I get this:
ƒ Tus(uppy, opts) {
_classCallCheck(this, Tus);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));
_this.type = 'uploader';
_this.id = 'Tus';
_this.titl…
It seems that on your working example (before code split), you're importing the default export from `'./components/test'.
After you dynamically import to allow code-splitting, you should use Tus.default to achieve the same result. You can read more about it on webpack code splitting documentation.
In other words, import('./component/test').then(Tus => Tus.default)
I hope this helps! Cheers!
You can aslo use react-loadable it provides you loading component fallback:
function Loading() {
return <div>Loading...</div>;
}
const Test= Loadable({
loader: () => import('./components/test'),
loading: Loading,
});
In your route:
<Route exact path="/" component={Test} />
You should have installed:
in your package.json:
"#babel/plugin-syntax-dynamic-import": "7.0.0-beta.54",
in .babelrc
"plugins": [
"#babel/plugin-syntax-dynamic-import",]
It works great.

HOC import TypeError: Object(...) is not a function

I just tried to use a simple HOC with react.
Here is the function :
import React from "react"
const withOptions = (WrappedComponent) => {
return class extends React.Component {
render() {
return <WrappedComponent { ...this.props } />
}
}
}
export default withOptions
The problem seems to be in the way i export/import it.
Imported and used in a simple way, it works :
import withOptions from "./Options"
...
class BilanClimatique extends React.Component{
...
}
const StyledBilanClimatique = withStyles(styles)(BilanClimatique)
export default withOptions(StyledBilanClimatique)
But if i use an intermediate file like index.js
import withOptions from "./Options"
export {
withOptions
}
And import it in my component like that
import {
withOptions
} from "./index"
Here is what i get
Can someone help me understand this ?
EDIT :
I found that the component that is using the HOC is imported from the same file as the HOC :
import withOptions from "./Options"
import BilanClimatique from "./BilanClimatique"
export {
withOptions,
BilanClimatique
}
And that causes the problem, but I don't understand why...
Here is a sandbox with the problem https://codesandbox.io/s/r074735yvo
This seems to be a problem with hoisting of 'exports'. From what I can see, the imports get hoisted, but I could not see anything similar for exports.
The flow which causes problem (codesandbox):
App.js:
import { BilanClimatique } from "./components/index";
./components/index.js:
// just using the "re-export" shortcut
export { default as BilanClimatique } from "./BilanClimatique";
export { default as withOptions } from "./Options";
./components/BilanClimatique.js:
import { withOptions } from "./index";
./components/Options.js:
const withOptions = WrappedComponent => {
return ... //snipped code
export default withOptions;
When App.js asks index.js for BilanClimatique, it in turn asks the same index.js for withOptions. But since exports don't seem to be hoisted, index.js has not yet made withOptions available.
How to solve:
Ordered exports:
in ./components/index.js, change the order of exports as per your dependency:
// just using the "re-export" shortcut
export { default as withOptions } from "./Options";
export { default as BilanClimatique } from "./BilanClimatique";
I would not recommend it. It is very fragile.
Use index.js to only expose to outside your namespace. Inside your namespace, rely on explicit imports.
i.e. in ./components/BilanClimatique.js:
import withOptions from "./Options";
If you have a very large codebase, use multiple index.js for exporting your "contracts". Take a look at the codebases of various library authors, I think that is the strategy they take.
I would personally recommend #2 over #3 unless you run into problems with #2.
. doesn't look as a great import path. Try to import from 'index' file.
import {
Logo,
withOptions
} from "./index"

Export from /node_module and ./someFile treated different?

I've just moved some components I use in multiple projects to a private NPM module. For some reason though my build process is now generating the following errors for all the components that were moved:
Module parse failed:
C:\xampp\htdocs\wizer\packages\wizer-atoms\components\Textarea\index.js
Unexpected token (7:21) You may need an appropriate loader to handle
this file type.
Do all NPM modules need to be transpiled by default? Because I did not change any thing to the content. And moving the file back resolves the error.
Example component
import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import classnames from "classnames";
class Textarea extends PureComponent {
render() {
const { className, ...otherProps } = this.props;
return <textarea className={classnames("FORM__textfield", className)} />;
}
}
export default Textarea;
My index.js file of the NPM module
const req = require.context(".", true, /\.\/components\/[^/]+\/index\.js/);
req.keys().forEach((key) => {
const componentName = key.replace(/^.+\/([^/]+)\/index\.js/, "$1");
module.exports[componentName] = req(key).default;
});
This basically takes all files in the components directory and exports it. This allows me to use import { Textarea } from wizer-atoms;.

Categories