[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"]
}
}
}
Related
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);
}
}
I am not sure if react router is not working correctly or if I am missing something.
I have something like this
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'mobx-react';
import { configure } from 'mobx';
import createBrowserHistory from 'history/createBrowserHistory';
import {syncHistoryWithStore } from 'mobx-react-router';
import { Router } from 'react-router'
import AppContainer from './components/App';
const browserHistory = createBrowserHistory();
import stores from '../src/stores/Stores';
const history = syncHistoryWithStore(browserHistory, stores.routingStore);
configure({ enforceActions: true});
ReactDOM.render(
<Provider {... stores}>
<Router history={history}>
<AppContainer />
</Router>
</Provider>,
document.getElementById('app')
);
Then in my AppContainer I have this
import { withRouter, Route, Link } from "react-router-dom";
<Route path="/company-details/company/:companyId/employee/:employeeId" component={CompanyComponent} />
and
<Link to="/company-details/company/76/employee/77"></Link>
now when I click on the link, it goes to the right page and I got access to the parameters.
but say if I did ctrl + click to make a new tab while clicking on the link or refreshing the page.
I get
GET http://localhost:8080/company-details/company/76/employee/index_bundle.js 404 (Not Found)
Refused to execute script from 'http://localhost:8080/company-details/company/76/employee/index_bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
I have these packages installed
"react-router-dom": "^4.2.2"
"mobx-react-router": "^4.0.4",
Edit
my webpack.config
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: ["babel-polyfill", "./src/index.js"],
output: {
path: path.join(__dirname, "/dist"),
filename: "index_bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /(\.css|\.scss|\.sass)$/,
use: [
{
loader: "style-loader" // creates style nodes from JS strings
},
{
loader: "css-loader" // translates CSS into CommonJS
},
{
loader: "sass-loader" // compiles Sass to CSS
}
]
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
devServer: {
historyApiFallback: true
}
};
Inside index.html you should link your script file like following:
<script type="text/javascript" src="./index_bundle.js"></script>
I am working on project using Vue.js, bundling with Rollup.
Here is my rollup.config.js file
import vue from 'rollup-plugin-vue2'
import less from 'rollup-plugin-less2';
import buble from 'rollup-plugin-buble'
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import uglify from 'rollup-plugin-uglify'
import livereload from 'rollup-plugin-livereload'
import serve from 'rollup-plugin-serve'
const plugins = [
vue({'css':'none'}),
less({output: "dist/build.css"}),
buble({exclude: 'node_modules/**'}),
nodeResolve({browser: true, jsnext: true}),
commonjs()
]
if (process.env.NODE_ENV === 'production') {
plugins.push(uglify())
}
if (process.env.NODE_ENV === 'development') {
plugins.push(livereload('dist'))
plugins.push(serve({
contentBase: "",
open: true
}))
}
export default {
input: 'src/main.js',
output: {
file: 'dist/build.js',
format: 'iife',
sourcemap: true,
//external: ["vue","vue-router"],
},
//external: ["vue","vue-router"],
plugins
}
Here is my main.js file.
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router";
Vue.use(VueRouter);
const Foo = {template: '<div>foo</div>'}
const Bar = {template: '<div>bar</div>'}
const routes = [
{path: '/foo', component: Foo},
{path: '/bar', component: Bar}
];
const router = new VueRouter({
routes
});
var app = new Vue({
router: router,
el: '#app',
render: h => h(App)
});
I have this error after running my project
Uncaught ReferenceError: process is not defined
If I use Vue as external lib and uncomment this ["vue","vue-router"], external: ["vue","vue-router"] all working fine.
How to make my project compile and work with rollup?
I had the same problem. Found a solution here: https://github.com/rollup/rollup/issues/487
You have to use the rollup replace plugin to replace all calls to process.env.NODE_ENV in all imported files like so:
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify( 'production' )
})
]
I looked over the other threads, but it seems to me like I'm doing everything properly as best as I can tell. This only happens to me when I package and run my app. In development, this runs fine. I can't find the code that is making that difference though. Lots of code below.
Am I making a mistake in my implementation of React-Redux-Router? If so, I'm blind to it. Thanks for any help!
Uncaught Invariant Violation: Could not find "store" in either the context or props of "Connect(e)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(e)".
Index.js
import _ from 'lodash';
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import storage from 'electron-json-storage';
import { Router, hashHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import axios from 'axios';
import configureStore from './store/configureStore';
import routes from './routes';
let myState;
let createStore;
let history;
function createProvider() {
render(
<Provider store={createStore}>
<Router history={history} routes={routes} />
</Provider>,
document.getElementById('root')
);
}
function createStoreFunction() {
createStore = configureStore(myState);
history = syncHistoryWithStore(hashHistory, createStore);
}
createStoreFunction();
createProvider();
Routes.js
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import myMain from './containers/myMain';
export default (
<Route path="/" component={myMain}>
<IndexRoute component={myMain} />
</Route>
);
myMain.js
import React, { Component, PropTypes } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Header from '../components/Header';
import MainSection from '../components/MainSection';
import * as NoteActions from '../actions/notes_actions';
import style from './App.css';
#connect(
state => ({
notes: state.notes,
activeNote: state.activeNote
}),
dispatch => ({
actions: bindActionCreators(NoteActions, dispatch)
})
)
export default class myMain extends Component {
static propTypes = {
notes: PropTypes.array.isRequired,
activeNote: PropTypes.object,
actions: PropTypes.object.isRequired
};
render() {
const { notes, activeNote, actions } = this.props;
return (
<div className={style.normal}>
<MainSection actions={actions} />
</div>
);
}
}
Webpack.config.production.js
import webpack from 'webpack';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import merge from 'webpack-merge';
import baseConfig from './webpack.config.base';
export default merge(baseConfig, {
//devtool: 'cheap-module-source-map', // Real production
devtool: 'source-map', // Faux production
entry: './app/index',
output: {
publicPath: '../dist/'
},
module: {
loaders: [
{
test: /\.global\.css$/,
loaders: [
'style-loader',
'css-loader?sourceMap'
]
},
{
test: /^((?!\.global).)*\.css$/,
loaders: [
'style-loader',
'css-loader?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
]
}
]
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.optimize.UglifyJsPlugin({
compressor: {
screw_ie8: true,
warnings: false
}
}),
new ExtractTextPlugin('style.css', { allChunks: true })
],
target: 'electron-renderer'
});
enter code here
Webpack.config.development.js
/* eslint max-len: 0 */
import webpack from 'webpack';
import merge from 'webpack-merge';
import baseConfig from './webpack.config.base';
const port = process.env.PORT || 3000;
export default merge(baseConfig, {
debug: true,
devtool: 'source-map',
entry: [
`webpack-hot-middleware/client?path=http://localhost:${port}/__webpack_hmr`,
'./app/index'
],
output: {
publicPath: `http://localhost:${port}/dist/`
},
module: {
loaders: [
{
test: /\.global\.css$/,
loaders: [
'style-loader',
'css-loader?sourceMap'
]
},
{
test: /^((?!\.global).)*\.css$/,
loaders: [
'style-loader',
'css-loader?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
]
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
],
target: 'electron-renderer'
});
configureStore.prod.js
import { applyMiddleware, createStore, compose } from 'redux';
import {responsiveStoreEnhancer} from 'redux-responsive';
import thunk from 'redux-thunk';
import { hashHistory } from 'react-router';
import { routerMiddleware, push } from 'react-router-redux';
import rootReducer from '../reducers';
import storage from '../utils/storage';
const router = routerMiddleware(hashHistory);
const enhancer = compose(
responsiveStoreEnhancer,
applyMiddleware(thunk, router),
storage(),
window.devToolsExtension ? window.devToolsExtension({ }) : nope => nope
);
export default function configureStore(initialState) {
const store = enhancer(createStore)(rootReducer, initialState);
if (window.devToolsExtension) {
window.devToolsExtension.updateStore(store);
}
return store;
}
configureStore.dev.js
import { applyMiddleware, createStore, compose } from 'redux';
import {responsiveStoreEnhancer} from 'redux-responsive';
import thunk from 'redux-thunk';
import { hashHistory } from 'react-router';
import { routerMiddleware, push } from 'react-router-redux';
import rootReducer from '../reducers';
import storage from '../utils/storage';
import * as noteActions from '../actions/notes_actions';
import createLogger from 'redux-logger';
const actionCreators = {
...noteActions,
push,
};
const logger = createLogger({
level: 'info',
collapsed: true,
});
const router = routerMiddleware(hashHistory);
const enhancer = compose(
responsiveStoreEnhancer,
applyMiddleware(thunk, router, logger),
storage(),
window.devToolsExtension ? window.devToolsExtension({ actionCreators }) : nope => nope
);
export default function configureStore(initialState) {
const store = enhancer(createStore)(rootReducer, initialState);
if (module.hot) {
module.hot.accept('../reducers', () => {
const nextRootReducer = require('../reducers');
store.replaceReducer(nextRootReducer);
});
}
return store;
}
Index.html
<!DOCTYPE html>
<html tabindex="-1">
<head>
<meta charset="UTF-8">
<div id="root"></div>
<script>
{
const script = document.createElement('script');
const port = process.env.PORT || 3000;
script.src = (process.env.HOT) ? `http://localhost:${port}/dist/bundle.js` : '../dist/bundle.js';
document.write(script.outerHTML);
}
</script>
<script>
if (!process.env.HOT) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '../dist/style.css';
document.write(link.outerHTML);
}
</script>
</body>
</html>
This is all new and no doubt I'm doing something stupid, but I have a component that I can't get to show up.
Here's my webpack.config.js
var path = require('path');
var webpack = require('webpack');
var bootstratp = require('react-bootstrap');
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./src/index',
],
output: {
path: path.join(__dirname, 'dist'),
//path: 'build',
filename: 'bundle.js',
publicPath: '/static/'
},
resolve:{
extensions:['','.js','.jsx']
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'src')
}]
}
};
Here's the index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
Here's the App.js
import React, { Component } from 'react';
import {Button} from 'react-bootstrap';
import TestBox from './components/test';
var path = require('path');
export default class App extends Component {
render() {
return (
<div>
<h1>aaa</h1>
<TestBox/>
</div>
);
}
}
Finally here's the component that isn't showing up:
export default
TestBox = React.createClass({
render:function(){
return <div>ABCD</div>
}
});
You don't need to put an equal sign in front of the export default:
try this, similar to how you have it in App.js:
let TestBox = React.createClass({
render:function(){
return <div> ABCD </div>
}
});
export default TextBox