ERROR ReferenceError: React is not defined | Using React Components in Angular - javascript

So basically I want to render one single React component (a notification component) into my Angular project. I created Notification.tsx
import * as React from 'react';
import { FunctionComponent, useEffect, useRef, useState } from 'react';
import { IconButton, Badge, Menu, List, ListItem, ListItemIcon, ListItemText, ListItemSecondaryAction, Avatar } from '#material-ui/core';
import { Notifications, Delete, Event, HourglassEmpty, Alarm } from '#material-ui/icons';
import { makeStyles } from '#material-ui/core/styles';
import { grey } from '#material-ui/core/colors';
export interface NotificationProps { }
export const NotificationComponent: FunctionComponent<NotificationProps> = (props: NotificationProps) => {
return <div className={"row"}>
<IconButton disableRipple={true} aria-label="notification" className="py-3 my-auto"
onClick={handleNotificationMenuClick} aria-controls="notification-drop-down-menu"
aria-haspopup="true">
<Badge badgeContent={4} max={99} color="secondary">
<Notifications />
</Badge>
</IconButton>
</div>
};
A wrapper component NotificationWrapper.tsx
import { AfterViewInit, Component, ElementRef, OnChanges, OnDestroy, SimpleChanges, ViewChild, ViewEncapsulation } from '#angular/core';
import { NotificationComponent } from './Notification';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const containerElementName = 'notificationComponentTemplate';
#Component({
selector: 'react-notification-component',
template: `<span #${containerElementName}></span>`,
encapsulation: ViewEncapsulation.None,
})
export class NotificationWrapper implements OnChanges, OnDestroy, AfterViewInit {
#ViewChild(containerElementName, { static: false }) containerRef: ElementRef;
constructor() { }
ngOnChanges(changes: SimpleChanges): void {
this.render();
}
ngAfterViewInit() {
this.render();
}
ngOnDestroy() {
ReactDOM.unmountComponentAtNode(this.containerRef.nativeElement);
}
private render() {
ReactDOM.render(<div className={'notification-wrapper'}>
<NotificationComponent />
</div>, this.containerRef.nativeElement);
}
}
Added this wrapper to app.module.ts's #NgModule
import { NotificationWrapper } from "../react-components/notification/NotificationWrapper";
#NgModule({
declarations: [
NotificationWrapper,
],
})
Used the notification wrapper selector as follows:
<div class="col-sm-6">
<react-notification-component></react-notification-component>
</div>
Everything works fine when served locally and as I went through other similar questions on this site: I've added "jsx": "react" to tsconfig.json,
plugins: [
new webpack.ProvidePlugin({
"React": "react",
})
]
and
externals: {
'react': 'React'
},
to webpack.config.js. Here's the whole file for reference.
// Work around for https://github.com/angular/angular-cli/issues/7200
const path = require('path');
const webpack = require('webpack');
// change the regex to include the packages you want to exclude
const regex = /firebase\/(app|firestore)/;
module.exports = {
mode: 'production',
entry: {
// This is our Express server for Dynamic universal
server: './server.ts'
},
externals: {
'./dist/server/main': 'require("./server/main")',
'react': 'React'
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},
resolve: { extensions: ['.ts', '.js'] },
target: 'node',
mode: 'none',
// this makes sure we include node_modules and other 3rd party libraries
externals: [/node_modules/, function (context, request, callback) {
// exclude firebase products from being bundled, so they will be loaded using require() at runtime.
if (regex.test(request)) {
return callback(null, 'commonjs ' + request);
}
callback();
}],
optimization: {
minimize: false
},
output: {
// Puts the output at the root of the dist folder
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
noParse: /polyfills-.*\.js/,
rules: [
{ test: /\.ts$/, loader: 'ts-loader' },
{
// Mark files inside `#angular/core` as using SystemJS style dynamic imports.
// Removing this will cause deprecation warnings to appear.
test: /(\\|\/)#angular(\\|\/)core(\\|\/).+\.js$/,
parser: { system: true },
},
]
},
plugins: [
new webpack.ProvidePlugin({
"React": "react",
}),
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
};
My problem is, when I build my app, the notification component is not rendered and I get this error in console ERROR ReferenceError: React is not defined. Is there anything that I missed? Thanks in advance.

Add the following to tsconfig.json
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"jsx": "react",
}
Set aot and buildOptimizer to false in angular.json
Replace
import * as React from 'react';
import * as ReactDOM from 'react-dom'
with
import React from 'react';
import ReactDOM from 'react-dom';

I think it's a typical unwanted optimization that remove React in the final js (React isn't directly used)
Try to call a method or an attribute on React like React.version :
import {
OnChanges,
ViewChild
} from '#angular/core';
import { MyComponent } from './react/MyComponent';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const containerElementName = 'myReactComponentContainer';
#Component({
...
})
export class MyComponent implements OnChanges {
#ViewChild(containerElementName) containerRef: ElementRef;
ngOnChanges(changes: SimpleChanges): void {
this.render();
}
private render() {
React.version;
ReactDOM.render(<MyReactComponent />, this.containerRef.nativeElement);
}
}

Related

How to include Tailwind CSS styles from React component library into the app CSS bundle?

G'day,
I am building a React component library with TailwindCSS and ViteJS. The library outputs each component as a separate JS file, for example:
// #components-library/src/ComponentA.jsx
export default function ComponentA() {
return <div className="flex justify-center">Component A</div>;
}
// Bundle Output: #components-library/dist/ComponentA.js
import { j as jsx } from "./jsx-runtime.js";
import "react";
function ComponentA() {
return /* #__PURE__ */ jsx("div", {
className: "flex justify-center",
children: "Component A",
});
}
export { ComponentA as default };
The app that is consuming this components library is also using Tailwind. However, the styles are not applied to the imported component. App-specific styles are working fine.
/* app/src/index.css */
#tailwind base;
#tailwind components;
#tailwind utilities;
// app/src/App.jsx
import CompoenntA from "#component-library/ComponentA";
export default function App() {
return (
<div className="p-10">
<ComponentA />
</div>
);
}
Awaiting expert advice.
Thank you!
Currently, I am also working on a similar project as like as you. I have built my component library with rollup. It generated a CSS file then imported that CSS file to my main package.
My Rollup Config
import resolve from "#rollup/plugin-node-resolve";
import babel from "#rollup/plugin-babel";
import commonjs from "#rollup/plugin-commonjs";
import typescript from "#rollup/plugin-typescript";
import { terser } from "rollup-plugin-terser";
import external from "rollup-plugin-peer-deps-external";
import postcss from "rollup-plugin-postcss";
import swc from "rollup-plugin-swc";
import filesize from "rollup-plugin-filesize";
const packageJson = require("./package.json");
export default [
{
input: "index.ts",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: false,
name: "#ht/components",
},
{
file: packageJson.module,
format: "esm",
sourcemap: false,
},
],
plugins: [
babel({
// this is needed because we're using TypeScript
babelHelpers: "bundled",
extensions: [".ts", ".tsx"],
}),
external(),
resolve(),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" }),
postcss({
config: {
path: "./postcss.config.js",
},
extensions: [".css"],
minimize: true,
extract: "lib.css",
}),
swc({
jsc: {
parser: {
syntax: "typescript",
},
target: "es2018",
},
}),
terser(),
filesize(),
],
},
];
Main Package's index
import "#ht/components/dist/cjs/lib.css";
import "./assets/css/tailwind.css";
You should add the path of the component to the tailwind.config.js.
In my case, my component library is symlinked to the current project using yarn link and the same problem was happening. Here is what I added in tailwind.config.js:
module.exports = {
// use content instead of purge if using tailiwind v3
purge: [
"./src/**/*.{js,jsx,ts,tsx}",
"./public/index.html",
// this line fixed the issue for me
"./node_modules/{component-library-name}/src/**/*.{js,jsx,ts,tsx}"
],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {}
},
variants: {
extend: {}
},
plugins: []
};

Importing React Component with JSX

There was a problem with importing react component with JXS. Components are imported from library (used like a SDK).
/sdk/dist/js/app.js
import React, { Component } from 'react';
export default class Test extends Component {
render() {
return <div>Hello</div>;
}
}
There is a project where this SDK is used, there is webpack / babel that already does a build, the file with import of this component looks like this:
app/js/index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Test from 'sdk/dist/js/App';
Result:
BUT!
Everything will work if:
We remove JSX from this component
app/js/index.js
import React, { Component } from 'react';
export default class Test extends Component {
render() {
return React.createElement(
"div",
null,
"Hello"
);
}
}
Remove import and insert component directly.
app/js/index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Test extends Component {
render() {
return <div>Hello</div>;
}
}
The problem is that it needs to work through import. I suggest that the problem is that the webpack does not transpose the imported file - and reads it as is ...
webpack:
{
entry: './app/js/index.js',
output: {
path: resolve(__dirname, plConfig.paths.public.root),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: [
{
loader: "babel-loader",
options: {
cacheDirectory: true
}
}
]
}
]
}
.babelrc:
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
]
}
You'll need a babel plugin to transform jsx...
#babel/plugin-transform-react-jsx
Install
npm i -D #babel/plugin-transform-react-jsx
Use in .babelrc
{
presets: [ ... ],
plugins: [ "#babel/plugin-transform-react-jsx", ...other plugins ]
}
EDIT:
You also need to add a babel rule for jsx...
In your webpack module rules...
Change test: /\.js$/ to test: /\.jsx?$/

Loading jsx file in react-component

I have components/Header/index.jsx looking like this:
import React from 'react';
import PropTypes from 'prop-types';
import Breadcrumb from '../Breadcrumb';
// import styled from 'styled-components';
import Logo from '../Logo';
/* eslint-disable react/prefer-stateless-function */
class Header extends React.Component {
render() {
const providerId = (this.props.profileData.profileData.length > 0) ? this.props.profileData.profileData[0].provider_id : null;
if (!providerId) {
return "Loading...";
}
const certifStatus = (this.props.profileData.profileData.length > 0) ? this.props.profileData.profileData[0].certification_status : null;
let showInfo = false;
if (certifStatus === 'certified'){
showInfo = true;
}
return (
<div className="header">
<div className="header__top">
<div className="container-fluid">
<div className="row">
<div className="col-12">
<a href="/" className="header__logo">
<Logo providerId={providerId} />
</a>
<span style={{ marginLeft: '4px' }} className="header__title">
{this.props.text}
</span>
</div>
</div>
</div>
</div>
<Breadcrumb text="Artist certification" link="https://www.believebackstage.com/" showInfo={showInfo} infoLink="#"/>
</div>
);
}
}
Header.propTypes = {
profileData: PropTypes.object,
text: PropTypes.string,
};
export default Header;
When I try to import it into containers/ProfilePage/index.js
import Header from '../../components/Header/index.jsx';
It throws:
ERROR in ./app/components/Header/index.jsx 28:6
Module parse failed: Unexpected token (28:6)
You may need an appropriate loader to handle this file type.
| }
| return (
> <div className="header">
| <div className="header__top">
| <div className="container-fluid">
# ./app/containers/ProfilePage/index.js 30:0-55 69:28-34
# ./app/containers/ProfilePage/Loadable.js
# ./app/containers/App/index.js
# ./app/app.js
# multi eventsource-polyfill webpack-hot-middleware/client?reload=true ./app/app.js
It seems as if it is a webpack issue, so here is how my internals/webpack/webpack.base.babel.js looks like:
/**
* COMMON WEBPACK CONFIGURATION
*/
const path = require('path');
const webpack = require('webpack');
// Remove this line once the following warning goes away (it was meant for webpack loader authors not users):
// 'DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic,
// see https://github.com/webpack/loader-utils/issues/56 parseQuery() will be replaced with getOptions()
// in the next major version of loader-utils.'
process.noDeprecation = true;
module.exports = options => ({
mode: options.mode,
entry: options.entry,
output: Object.assign(
{
// Compile into js/build.js
path: path.resolve(process.cwd(), 'build'),
publicPath: '/',
},
options.output,
), // Merge with env dependent settings
optimization: options.optimization,
module: {
rules: [
{
test: /\.(js|jsx)$/, // Transform all .js files required somewhere with Babel
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: options.babelQuery,
},
},
{
// Preprocess our own .css files
// This is the place to add your own loaders (e.g. sass/less etc.)
// for a list of loaders, see https://webpack.js.org/loaders/#styling
test: /\.scss$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
// Preprocess 3rd party .css files located in node_modules
test: /\.css$/,
include: /node_modules/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(eot|otf|ttf|woff|woff2)$/,
use: 'file-loader',
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-url-loader',
options: {
// Inline files smaller than 10 kB
limit: 10 * 1024,
noquotes: true,
},
},
],
},
{
test: /\.(jpg|png|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// Inline files smaller than 10 kB
limit: 10 * 1024,
},
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
enabled: false,
// NOTE: mozjpeg is disabled as it causes errors in some Linux environments
// Try enabling it in your environment by switching the config to:
// enabled: true,
// progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
pngquant: {
quality: '65-90',
speed: 4,
},
},
},
],
},
{
test: /\.html$/,
use: 'html-loader',
},
{
test: /\.(mp4|webm)$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
},
},
},
],
},
plugins: options.plugins.concat([
new webpack.ProvidePlugin({
// make fetch available
fetch: 'exports-loader?self.fetch!whatwg-fetch',
}),
// Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV`
// inside your code for any environment checks; UglifyJS will automatically
// drop any unreachable code.
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
},
}),
]),
resolve: {
modules: ['node_modules', 'app'],
extensions: ['.js', '.jsx', '.react.js'],
mainFields: ['browser', 'jsnext:main', 'main'],
},
devtool: options.devtool,
target: 'web', // Make web variables accessible to webpack, e.g. window
performance: options.performance || {},
});
I've tried solutions from several similar questions like this one.
Note:
I'm using this react boilerpalte.
Please help me unstuck folks.
After having looked at the docs a little closer here is how I got it to work...
Take a look here: https://github.com/react-boilerplate/react-boilerplate/tree/master/docs/js
They are using plop to autogenerate components containers etc...
So you simply do: npm run generate and follow the prompts...
I did and created a container called ProfilePage...
In my ProfilePage I imported the Header (the rest it simply auto-generated, the only thing I added was the import statement:
Here it is:
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Helmet } from 'react-helmet';
import { FormattedMessage } from 'react-intl';
import { createStructuredSelector } from 'reselect';
import { compose } from 'redux';
// Here is my import (notice no relative path needed)
import Header from 'components/Header';
import injectSaga from 'utils/injectSaga';
import injectReducer from 'utils/injectReducer';
import makeSelectProfilePage from './selectors';
import reducer from './reducer';
import saga from './saga';
import messages from './messages';
/* eslint-disable react/prefer-stateless-function */
export class ProfilePage extends React.Component {
render() {
return (
<div>
<Helmet>
<title>ProfilePage</title>
<meta name="description" content="Description of ProfilePage" />
</Helmet>
<FormattedMessage {...messages.header} />
// Here is where I render it
<Header />
</div>
);
}
}
ProfilePage.propTypes = {
dispatch: PropTypes.func.isRequired,
};
const mapStateToProps = createStructuredSelector({
profilepage: makeSelectProfilePage(),
});
function mapDispatchToProps(dispatch) {
return {
dispatch,
};
}
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
);
const withReducer = injectReducer({ key: 'profilePage', reducer });
const withSaga = injectSaga({ key: 'profilePage', saga });
export default compose(
withReducer,
withSaga,
withConnect,
)(ProfilePage);
That whole thing with the exception of the import Header from 'components/Header' and the rendering of header <Header /> just below <FormattedMessage {...messages.header} /> was auto-generated using plop
Then I simply imported ProfilePage in my App/index.js and added a route... Now when I navigate to localhost:3000/profile the ProfilePage shows up along with the Header...
Here is the App/index.js:
import React from 'react';
import { Helmet } from 'react-helmet';
import styled from 'styled-components';
import { Switch, Route } from 'react-router-dom';
import HomePage from 'containers/HomePage/Loadable';
import FeaturePage from 'containers/FeaturePage/Loadable';
import NotFoundPage from 'containers/NotFoundPage/Loadable';
import Header from 'components/Header';
import Footer from 'components/Footer';
// Here is where I import it...
import ProfiePage from 'containers/ProfilePage';
const AppWrapper = styled.div`
max-width: calc(768px + 16px * 2);
margin: 0 auto;
display: flex;
min-height: 100%;
padding: 0 16px;
flex-direction: column;
`;
export default function App() {
return (
<AppWrapper>
<Helmet
titleTemplate="%s - React.js Boilerplate"
defaultTitle="React.js Boilerplate"
>
<meta name="description" content="A React.js Boilerplate application" />
</Helmet>
<Header />
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/features" component={FeaturePage} />
// Here is the route I added...
<Route path="/profile" conmponent={ProfiePage} />
<Route component={NotFoundPage} />
</Switch>
<Footer />
</AppWrapper>
);
}
In conclusion, if you're going to use this boilerplate you absolutely need to go through their docs...

webpack-dev-server with hot reload reloading entire page with css changes

[Edit]
Github Test Repo Created for you to test!!
I have hot reloading without any problems, but it reloads the entire page whenever I make a single css change. I would like it to inject any css changes and ideally do similarly with react components unless a full reload is truly needed.
** I get the following console logs **
[WDS] App updated. Recompiling...
client?cd17:41 [WDS] App updated. Recompiling...
client?8505:41 [WDS] App updated. Recompiling...
client?cd17:41 [WDS] App updated. Recompiling...
client?8505:41 [WDS] App hot update...
dev-server.js:45 [HMR] Checking for updates on the server...
client?cd17:41 [WDS] App hot update...
dev-server.js:33 [HMR] Cannot apply update. Need to do a full reload!
(anonymous) # dev-server.js:33
dev-server.js:34 [HMR] Error: Aborted because ./node_modules/css-loader/index.js?{"modules":true,"sourceMap":true,"importLoaders":2,"localIdentName":"[path]___[name]__[local]___[hash:base64:5]"}!./node_modules/postcss-loader/index.js?sourceMap&parser=postcss-scss!./src/components/shared/userPages/userPages.css is not accepted
Update propagation: ./node_modules/css-loader/index.js?{"modules":true,"sourceMap":true,"importLoaders":2,"localIdentName":"[path]___[name]__[local]___[hash:base64:5]"}!./node_modules/postcss-loader/index.js?sourceMap&parser=postcss-scss!./src/components/shared/userPages/userPages.css -> ./src/components/shared/userPages/userPages.css -> ./src/components/Signin/index.js -> ./src/routes.js -> ./src/index.js -> 0
at hotApply (http://localhost:8080/dist/main.js:430:30)
at hotUpdateDownloaded (http://localhost:8080/dist/main.js:283:13)
at hotAddUpdateChunk (http://localhost:8080/dist/main.js:263:13)
at webpackHotUpdateCallback (http://localhost:8080/dist/main.js:8:12)
at http://localhost:8080/dist/0.75f9c418ba8b1fdc9ad0.hot-update.js:1:1
webpack config
/* eslint-disable */
const Config = require('webpack-config').default;
const webpack = require('webpack');
const DashboardPlugin = require('webpack-dashboard/plugin');
const {environment} = require('webpack-config');
const path = require('path');
environment.set('cssIdent', '[path]___[name]__[local]___[hash:base64:5]');
module.exports = new Config().extend('./webpack.base.config.js').merge({
entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./src/index.js'
],
devServer: {
contentBase: [
'demo/'
],
hot: true,
historyApiFallback: true,
host: '0.0.0.0',
publicPath: '/dist/'
},
output: {
filename: 'main.js',
path: path.join(__dirname, 'dist'),
publicPath: '/dist/'
},
devtool: 'inline-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': {
BABEL_ENV: JSON.stringify('development')
}
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new DashboardPlugin()
],
cache: true
});
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import { AppContainer } from 'react-hot-loader';
import { ConnectedRouter } from 'react-router-redux'
import injectTapEventPlugin from 'react-tap-event-plugin';
import nprogress from 'nprogress';
import store from './configureStore';
import Routes from './routes';
import './components/shared/main.css';
import createHashHistory from 'history/createHashHistory'
const history = createHashHistory({
hashType: 'slash'
});
//Remove on screen tap delay
injectTapEventPlugin();
//Add progress bar
nprogress.configure({ minimum: 0.15, showSpinner: false, speed: 500 });
// Now you can dispatch navigation actions from anywhere!
// store.dispatch(push('/foo'))
ReactDOM.render(
<AppContainer>
<Provider store={store}>
<ConnectedRouter history={history}>
<Routes/>
</ConnectedRouter>
</Provider>
</AppContainer>,
document.getElementById('app')
);
Store.js
import { createStore, applyMiddleware, compose } from 'redux'
import { createLogger } from 'redux-logger'
import { routerMiddleware } from 'react-router-redux'
import reducers from './reducers';
const configureStore = function (history, preloadedState = {}) {
// Build the middleware for intercepting and dispatching navigation actions
const middlewareHistory = routerMiddleware(history);
const store = createStore(
reducers,
preloadedState,
compose(
applyMiddleware(createLogger(), middlewareHistory)
)
);
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('./reducers', () => {
const nextReducer = require('./reducers').default;
store.replaceReducer(nextReducer);
});
}
return store;
};
export default configureStore(history);
A random component
import React from 'react';
import { NavLink } from 'react-router-dom'
import store from '../../configureStore';
import userStyles from '../shared/userPages/userPages.css';
class SignIn extends React.Component {
render(){
return (
<div className={userStyles.home}>
</div>
);
}
}
export default SignIn;
.babelrc
{
"presets": [
["es2015", {"modules": false}],
"stage-0",
"react"
],
"plugins": [
"react-hot-loader/babel"
],
"env": {
"development/client": {
"plugins": [
["transform-runtime", {
"helpers": false,
"polyfill": false,
"regenerator": true
}]
]
},
"test": {
"presets": ["es2015"],
"plugins": [
["transform-runtime", {
"helpers": false,
"polyfill": false,
"regenerator": true
}]
]
}
}
}
you can use extract text webpack plugin for css hot reloading instead of whole page/module reloading.
below is the guideline to know how to use
https://github.com/webpack-contrib/extract-text-webpack-plugin
https://www.npmjs.com/package/extract-text-webpack-plugin
For me it didn't work because I didn't have .babelrc file in my root directory and with below code inside it.
{
"env": {
"development": {
"presets": ["react-hmre"]
}
}
}

Error trying to do an hybrid AngularJS/Angular app

Im trying to do an hybrid app using AngularJS & Angular(2).
I already have a big AngularJS app and I just want to use a component from an Angular app.
Using https://angular.io/docs/ts/latest/guide/upgrade.html, I have created two new files
app.module.ts
import { UpgradeModule } from '#angular/upgrade/static';
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
#NgModule({
imports: [
BrowserModule,
UpgradeModule,
],
})
export class AppModule {
ngDoBootstrap() {}
}
and main.ts
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { UpgradeModule } from '#angular/upgrade/static';
import { AppModule } from './app.module';
import App from './app.js';
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.documentElement, [App]);
});
and I have deleted the old bootstrap.js file
import angular from 'angular';
import App from './app';
angular.element(function() {
angular.bootstrap(document, [App], { strictDi: true });
});
The entry of my webpack build is now main.ts.
When I start my app, I have ana issue :
ERROR in ./client/app/main.ts
Module not found: Error: Can't resolve './app.module' in '/home/bsousa/Projects/S6/client/app'
# ./client/app/main.ts 5:21-44
Do someone know why ?
Here is the tsconfig.json, maybe it can help
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"allowJs": true,
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"allowUnreachableCode": true
},
"exclude": [
"node_modules"
]
}
Files structure
/
client
app
...
app.js
app.module.ts
main.ts
gulpfile.js
webpack.config.js
Well I don't know why the import did not work but when I set everything in the main.ts file, it works
import 'zone.js';
import 'angular';
import App from './app.js';
import { NgModule } from '#angular/core';
import { UpgradeModule } from '#angular/upgrade/static';
import { BrowserModule } from '#angular/platform-browser';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
#NgModule({
imports: [
BrowserModule,
UpgradeModule,
],
})
export class AppModule {
ngDoBootstrap() {
}
}
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.documentElement, [App.name], { strictDi: true });
});
My AngularJS is bootstrapped with Angular.
Now I'm trying to import my Angular app into my project as a node package but I think I have to do some improvements with the export.
I would like to import the root component, do I have to import the root module as well ?

Categories