I have been working on this for two days now. Looked through multiple stack posts and still not found a suitable answer.
I am trying to rendering my react project in server like following:
Server.js
function handleRender(req,res){
const sheetsRegistry = new SheetsRegistry();
const sheetsManager = new Map();
const theme = createMuiTheme({
palette:{
primary:green,
accent: red,
type: 'light',
}
})
const generateClassName = createGenerateClassName();
const html = ReactDOMServer.renderToString(
<JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
<MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
<TwoFA />
</MuiThemeProvider>
</JssProvider>
)
const css = sheetsRegistry.toString()
res.send(renderFullPage(html,css))
}
function renderFullPage(html,css){
return `
<!DOCTYPE html>
<html>
<head>
<title>2FA SDK</title>
</head>
<body style="margin:0">
<div id="app">${html}</div>
<script id="jss-server-side">${css}</script>
</body>
</html>
`
}
Client.js:
import React from 'react';
import ReactDOM from 'react-dom';
import TwoFA from './App';
import {
MuiThemeProvider,
createMuiTheme,
createGenerateClassName,
} from '#material-ui/core/styles';
import green from '#material-ui/core/colors/green';
import red from '#material-ui/core/colors/red';
class Main extends React.Component{
componentDidMount() {
const jssStyles = document.getElementById('jss-server-side');
if (jssStyles && jssStyles.parentNode) {
jssStyles.parentNode.removeChild(jssStyles);
}
}
render(){
return <TwoFA />
}
}
const theme = createMuiTheme({
palette: {
primary: green,
accent: red,
type: 'light',
},
});
const generateClassName = createGenerateClassName();
if (typeof window !== 'undefined'){
ReactDOM.hydrate(
<JssProvider generateClassName={generateClassName}>
<MuiThemeProvider theme={theme}>
<TwoFA/>
</MuiThemeProvider>
</JssProvider>,
document.querySelector('#app'),
);
}
Webpack.config.js
module.exports = [
{
/*Config for backend code*/
entry: './src/server/server.js',
output: {
filename: 'server.js'
},
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: { minimize: true }
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader,"css-loader"]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./public/index.html",
filename:"./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename:"[id].css"
})
]
},
{
entry: './src/client.js',
output: {
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: { minimize: true }
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader,"css-loader"]
}
],
},
plugins: [
new HtmlWebPackPlugin({
template: "./public/index.html",
filename:"./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename:"[id].css"
})
]
}
]
What I have tried: I search on SO and found that many posts suggesting put a condition check like so : if (typeof window !== 'undefined'). However, this does not solve the problem.
I also understood that the error is due to the fact that during SSR, server-side has no document project.
I have searched on github issue page and someone mentioned that he ran into the problem with webpack, but same project worked fine with browserify.
What I need help with: I am trying to solve this problem as it cause the app to break.
I am suspecting that there is something wrong with webpack. I am looking a fix for this
This issue usually happens because when react is rendered on the server. It does not have a document or window object on the server side and those objects are only available on the browser.
Try to call the document functions in or after componentDidMount.
componentDidMount(){
this.setState({documentLoaded:true});
}
someFunction(){
const { documentLoaded } = this.state;
if(documentLoaded){
// LOGIC USING DOCUMENT OBJECT
}
}
If you are using react-hooks, you can create your custom useDocument hook:
import React, { useEffect, useState } from 'react'
export const useDocument = () => {
const [myDocument, setMyDocument] = useState(null)
useEffect(() => {
setMyDocument(document)
}, [])
return myDocument
}
in your component:
...
const doc = useDocument()
...
<SomeComponent
ref={doc && doc.body}
...
/>
...
Related
I had a working storybook but had to update to webpack5 to try and fix a sass issue... but that is now breaking the stories and I am not sure how to fix it.
I have a main.js on my <root>/.storybook folder:
const path = require('path');
module.exports = {
core: {
builder: 'webpack5',
},
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: "[name].[ext]",
outputPath: 'fonts/'
}
}
]
});
config.module.rules.push({
test: /\.(js|ts|tsx)$/,
use: [
{
loader: 'babel-loader',
}
],
});
config.module.rules.push(
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
include: path.resolve(__dirname, "../")
});
config.resolve.extensions = ['.ts', '.tsx', '.js'];
return config;
},
stories: ['../src/stories/storybook.js'] // <-- this used to work
};
My <root>/src/stories/storybook.js:
import 'core-js/stable';
import 'regenerator-runtime/runtime';
import { addDecorator } from '#storybook/react';
import { withA11y } from '#storybook/addon-a11y';
import StyleguideStory from './styleguide';
import './reset.css';
addDecorator(withA11y);
StyleguideStory('Styleguide');
And Basically styleGuide is a folder (<root>/src/stories/styleguide) with this index inside:
import Story1 from './Story1';
...
export default function StyleguideStory(nameRoot) {
Story1(nameRoot);
...
}
My stories are normally folders (<root>/src/stories/styleguide/<folders>) with an index:
import React from 'react';
import { storiesOf } from '#storybook/react';
import StoryExample from './StoryExample';
import StoryDoc from './StoryDoc';
export default function Story1(nameRoot) {
const story = storiesOf(`${nameRoot}/Story1`, module);
story.add('Examples', () => <StoryExample />);
story.add('Props', () => <StoryDoc />);
}
And each story is a normal function component... these all used to work before going to webpack, but I am not sure if I configured it wrong, or if this structure is not supported anymore....
I am making a Vue plugin that contains SFC with its own styles. I am using webpack4 to bundle. For production I use MiniCssExtractPlugin to extract CSS from SFC to separate file. Everything builds up correctly, style.css is created in dist folder and my plugin is working but seems like css from file is not loaded. Is there a step which I am missing?
Thank you
main.js
import SearchBar from "./components/Searchbar.vue";
const defaultOptions = {};
export let Search = {
install(Vue, options) {
let userOptions = { ...defaultOptions, ...options };
let props = { ...SearchBar.props };
Object.keys(userOptions).forEach(k => {
props[k] = { default: userOptions[k] };
});
Vue.component("SearchBarComponent", { ...SearchBar, props });
}
};
Searchbar.vue
<template>
<div class="search">My search template</div>
</template>
<script>
export default{
}
</script>
<style>
.search{
background-color:blue;
}
</style>
webpack.config.js
let path = require("path");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "./dist"),
libraryTarget: "commonjs2",
publicPath: "/dist/",
filename: "search.min.js"
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "style.css"
})
],
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader"
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: "file-loader",
options: {
name: "[name].[ext]?[hash]"
}
},
{
test: /\.css$/,
use: [
process.env.NODE_ENV !== "production"
? "vue-style-loader"
: MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
}
};
In my project, I just install my plugin from npm repository then I use
import {Search} from "my-search-plugin";
Vue.use(Search);
to import plugin, and then call
<SearchBarComponent>
wherever I need. The component appear successfully but styles and not applied.
I created a project using react native web and I got react native icons working for web and mobile except on storybook. I'm not sure how to tell storybooks webpack config to load FontAwesome fonts. I tried adding FontAwesome in the preview-head.html but Still not showing the icons just a rectangle as a placeholder. What I would like is to have my icons showing up in the storybook webpack server.
.storybook/main.js:
const webpack = require('webpack');
const path = require('path');
const rootDir = path.join(__dirname, '..');
module.exports = {
stories: ['../src/storybook/stories/*.stories.tsx'],
// addons: ['#storybook/addon-docs', '#storybook/addon-viewport', '#storybook/addon-knobs/', '#storybook/addon-links/', '#storybook/addon-actions/'],
webpackFinal: async config => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: require.resolve('awesome-typescript-loader'),
options: {
transpileOnly: true
}
}
],
},
{
test: /\.ttf$/,
loader: 'url-loader', // or directly file-loader
include: path.resolve(
__dirname,
'../node_modules/react-native-vector-icons',
),
},
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules[/\\](?!react-native|react-native-vector-icons|react-color|react-native-gesture-handler|#react-native-community|react-navigation|#react-navigation\/.*)/,
use: {
loader: 'babel-loader',
options: {
presets: [
'module:metro-react-native-babel-preset',
'#babel/preset-env',
'#babel/preset-flow',
'#babel/preset-typescript',
],
plugins: [
'#babel/plugin-proposal-class-properties',
'#babel/plugin-proposal-object-rest-spread',
'react-native-web',
],
},
},
},
)
config.plugins.push(
new webpack.DefinePlugin({
__DEV__: process.env.NODE_ENV !== 'production',
}),
);
config.resolve.alias = {
...(config.resolve.alias || {}),
'react-native': 'react-native-web',
'#storybook/react-native': '#storybook/react',
'#sentry/react-native': '#sentry/react',
'react-native-maps': 'react-native-web-maps',
'react-native-gesture-handler/GestureHandler': require.resolve(
'react-native-gesture-handler/GestureHandler',
),
'react-native-gesture-handler/RNGestureHandlerModule': path.join(
rootDir,
'node_modules',
'react-native-gesture-handler/RNGestureHandlerModule.web.js',
),
'./RNGestureHandlerModule': path.join(
rootDir,
'node_modules',
'react-native-gesture-handler/RNGestureHandlerModule.web.js',
),
'./GestureHandlerButton': path.join(
rootDir,
'node_modules',
'react-native-gesture-handler',
'GestureHandlerButton.web.js',
),
'./GestureComponents': path.join(
rootDir,
'node_modules',
'react-native-gesture-handler',
'GestureComponents.web.js',
),
'./PlatformConstants': path.join(
rootDir,
'node_modules',
'react-native-gesture-handler',
'PlatformConstants.web.js',
),
'#utilities': path.resolve(__dirname, '../src/utilities/'),
'#queries': path.resolve(__dirname, '../src/queries'),
'#pages': path.resolve(__dirname, '../src/components/pages'),
'#styled-components': path.resolve(
__dirname,
'../src/types/libraries/styled-components.ts',
),
'#hooks': path.resolve(__dirname, '../src/hooks'),
'#atoms': path.resolve(__dirname, '../src/components/atoms'),
'#molecules': path.resolve(__dirname, '../src/components/molecules'),
'#resources': path.join(__dirname, '../src/resources'),
'#providers': path.resolve(__dirname, '../src/providers'),
'#enums': path.resolve(__dirname, '../src/enums'),
'#common': path.resolve(__dirname, '../src/components/common'),
'#contexts': path.resolve(__dirname, '../src/contexts'),
'#util': path.resolve(__dirname, '../src/components/util'),
'#images': path.resolve(__dirname, '../src/assets/images'),
'#icons': path.resolve(__dirname, '../src/assets/icons'),
'#fonts': path.resolve(__dirname, '../src/assets/fonts'),
};
config.resolve.extensions.push('.ts', '.tsx');
config.module.rules[0].use[0].options.plugins.push(['react-native-web', { commonjs: true }]);
return config;
},
};
.storybook/preview-head.html
<link href="https://fonts.googleapis.com/css?family=Quicksand:400,700" rel="stylesheet">
<style type="text/css">
#font-face {
font-family: Quicksand-Bold;
src: url('https://fonts.gstatic.com/s/a/6bb475d143c61221c4ea174d3c51728268e58b12dbc14600d59020ef8deaaead.ttf');
}
#font-face {
font-family: Quicksand-Regular;
src: url('https://fonts.gstatic.com/s/a/0f408f35c3679417b5580701f3ac08830ce36535af5a643a2ef5b59e91c3c6b7.ttf');
}
#font-face {
font-family: Lato-Regular;
src: url('https://fonts.gstatic.com/s/a/a649aaf21573a59079c46db19314fd95648f531e610fa932101f2705616b2882.ttf');
}
#font-face {
font-family: Lato-Bold;
src: url('https://fonts.gstatic.com/s/a/407592da08cb1f6060fbc69262ad33edd0b61ec9160521455eca8f726bbd4353.ttf');
}
</style>
<script>
import FontAwesome from '../node_modules/react-native-vector-icons/FontAwesome.js';
// Generate required css
import {iconFont} from '../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf';
const iconFontStyles = `#font-face {
src: url(${iconFont});
font-family: FontAwesome;
}`;
// Create stylesheet
const style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = iconFontStyles;
} else {
style.appendChild(document.createTextNode(iconFontStyles));
}
// Inject stylesheet
document.head.appendChild(style);
try {
FontAwesome.loadFont();
console.log("working!");
} catch (e) {
console.log(e);
}
</script>
package.json
"storybook:web": "start-storybook -p 6006"
I think the problem exist in preview-head.html and I know I can't use import modules in the script tag but not sure where else to load fontAwesome so storybook can pick it up. Thanks!
The recommended approach for React Native with Storybook has changed since this question was answered. So if you're using #storybook/addon-react-native-web to get Storybook running in the browser, here's how I got custom fonts working.
I created the following FontLoader component, which wraps around my app's provider tree. So for Storybook, I added the loader to the global decorators in .storybook/preview.js. (And to be clear, I don't have any special webpack config.)
// FontLoader.tsx
import React, { PropsWithChildren, useCallback } from 'react'
import { View } from 'react-native'
import { useFonts } from 'expo-font'
import { theme, fontName } from '#theme'
interface Props extends PropsWithChildren {
onFontsLoaded?: () => void // callback for displaying the splash screen once background view has loaded
}
export const FontLoader = ({ onFontsLoaded, children }: Props) => {
const [fontsLoaded] = useFonts({
[fontName]: require('../../assets/fonts/Inter-Regular.otf'),
'inter-italic': require('../../assets/fonts/Inter-Italic.otf'),
'inter-light': require('../../assets/fonts/Inter-Light.otf'),
'inter-medium': require('../../assets/fonts/Inter-Medium.otf'),
'inter-bold': require('../../assets/fonts/Inter-Bold.otf'),
'inter-black': require('../../assets/fonts/Inter-Black.otf'),
})
const onLayoutRootView = useCallback(async () => {
if (fontsLoaded) {
onFontsLoaded?.()
}
}, [fontsLoaded, onFontsLoaded])
if (!fontsLoaded) {
return null
}
return (
<View onLayout={onLayoutRootView} style={{ flex: 1, backgroundColor: theme.colors.$background }}>
{children}
</View>
)
}
// .storybook/preview.js
import React from 'react'
import { FontLoader } from '../src/utils/FontLoader'
import { ThemeProvider } from '../src/theme'
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
export const decorators = [
Story => (
<FontLoader>
<ThemeProvider>
<Story />
</ThemeProvider>
</FontLoader>
),
]
For anyone having problems with this I needed to be specific on which file to be included for the url loader.
This change fixed the error:
{
test: /\.ttf$/,
loader: 'url-loader', // or directly file-loader
include: path.resolve(
__dirname,
'../node_modules/react-native-vector-icons/FontAwesome5.js',
),
},
I also moved the font awesome script into the preview.js file
when i try to npm start or npx webpack a project which i build about a simple rich text editor using reactjs,draft.js,webpack,and i encountered a problem that show me the compile information:
ERROR in ./src/index.js
Module not found: Error: Can't resolve '' in 'F:\draft_react\my_react'
# ./src/index.js 25:0-55
i am using npm#6.4.1,webpack#4.32.2,node-v10.15.3.
here is my package.json file details
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: './dist',
hot:true
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
};
and index.js file
import React, { Component } from 'react';
import Editor, { createEditorStateWithText } from 'draft-js-plugins-editor';
import createToolbarPlugin from 'draft-js-static-toolbar-plugin';
import editorStyles from './editorStyles.css';
import 'draft-js-static-toolbar-plugin/lib/plugin.css';
const staticToolbarPlugin = createToolbarPlugin();
const { Toolbar } = staticToolbarPlugin;
const plugins = [staticToolbarPlugin];
const text = 'The toolbar above the editor can be used for formatting text, as in conventional static editors …';
export default class SimpleStaticToolbarEditor extends Component {
state = {
editorState: createEditorStateWithText(text),
};
onChange = (editorState) => {
this.setState({
editorState,
});
};
focus = () => {
this.editor.focus();
};
render() {
return (
<div>
<div className={editorStyles.editor} onClick={this.focus}>
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
plugins={plugins}
ref={(element) => { this.editor = element; }}
/>
<Toolbar />
</div>
</div>
);
}
}
i am new to reactjs framework , i don't know how to solve this error for many hours.Thanks.
I have a problem. I cant refresh my react components/page without getting "Cannot GET /currentPage". I've browsed you for some time now and found a couple of links that could be the solution of my issue:
https://github.com/jintoppy/react-training/blob/master/basic/node_modules/react-router/docs/guides/Histories.md#browserhistory
HashHistory of BrowserHistory. Internet said I should use BrowserHistory for production - but that hashHistory is easier. They are both so effing complicated. I cant for my life figure out how to implement it to my current code.
This is my app.js file:
/*global $:true*/
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';
import './scss/app.scss';
// Component imports
import Home from './components/home';
import Archive from './archive';
// Image import
import loadImg from './images/tits.gif';
class App extends Component {
// Function for anchorlinks
hashLinkScroll() {
const { hash } = window.location;
if (hash !== '') {
// Push onto callback queue so it runs after the DOM is updated, this is required when navigating from a different page so that the element is rendered on the page before trying to getElementById
setTimeout(() => {
const id = hash.replace('#', '');
const element = document.getElementById(id);
if (element) element.scrollIntoView();
}, 100);
}
}
// 1. Render site-loader gif
// 2. React Router component wraps all of the routes we are going to define - Archive and Home. Each route will be identified in a <Route> component. The <Route> component will take two properties: path and component. When a path matches the path given to the <Route> component, it will return the component specified.
render() {
return (
<div>
<div className="loaderSmall">
<img className="loadingImg" src={loadImg} width="400"/>
</div>
<Router history={browserHistory} onUpdate={this.hashLinkScroll}>
<Route path={'/archive'} component={Archive} />
<Route path={'*'} component={Home} />
</Router>
</div>
);
};
// When Component has rendered, window.addEventListener adds event "load" and calls handleLoad function
componentDidMount() {
window.addEventListener('load', this.handleLoad);
}
// Fade out site-loader
handleLoad() {
$(".loaderSmall").delay(500).fadeOut("slow");
}
};
ReactDOM.render (
<App/>,
document.getElementById('app')
)
// Hot Module Replacement API (injecting code)
if (module.hot) {
module.hot.accept();
}
export default App;
..this is my menu component that renders when I am on "/archive" component:
import React, { Component } from 'react';
import { Link } from 'react-router';
//Menu component renders menu Link
class Menu extends Component {
render() {
return (
<header>
<nav>
<ul>
<li><Link to={'/#top'}>Home</Link></li>
<li><Link to={'/#about'}>About</Link></li>
<li><Link to={'/archive'}>Archive</Link></li>
<li className="contactMobile">Contact</li>
<li className="contactWeb"><Link to={'/#contact'}>Contact</Link></li>
</ul>
</nav>
</header>
);
}
}
export default Menu;
..and this is my other menu that renders when i am on root where i want scrollable hashlinks:
import React, { Component } from 'react';
import { Link } from 'react-router';
import Scrollchor from 'react-scrollchor';
//Menu component renders menu Link
class MenuB extends Component {
render() {
return (
<header>
<nav>
<ul>
<li><Scrollchor to="#top" animate={{offset: 20, duration: 800}}>Home</Scrollchor></li>
<li><Scrollchor to="#about" animate={{offset: 0, duration: 800}}>About</Scrollchor></li>
<li><Link to={'/archive'}>Archive</Link></li>
<li className="contactMobile">Contact</li>
<li className="contactWeb"><Scrollchor to="#contact" animate={{offset: 20, duration: 800}}>Contact</Scrollchor></li>
</ul>
</nav>
</header>
);
}
}
export default MenuB;
my webpack.config.js file:
// DEVELOPMENT
const webpack = require('webpack');
const path = require('path');
const entry = [
'webpack-dev-server/client?http://localhost:8080', // bundle the client for webpack-dev-server and connect to the provided endpoint
'webpack/hot/only-dev-server', // bundle the client for hot reloading only- means to only hot reload for successful updates
'./app.js'
]
const output = {
path: path.join(__dirname, 'dist'),
publicPath: '/dist',
filename: 'bundle.min.js'
}
const plugins = [
new webpack.HotModuleReplacementPlugin(), // enable HMR globally
new webpack.NamedModulesPlugin() // prints more readable module names in the browser console on HMR updates
]
const config = {
context: path.join(__dirname, 'src'),
entry: entry,
output: output,
devtool: "inline-source-map",
module: {
rules: [
{
// test: /\.(js|jsx)$/,
// exclude: /node_modules/,
// include: path.join(__dirname, 'src'),
// use: {
// loader: "eslint-loader",
// options: {
// failOnWarning: false,
// failOnError: false
// }
// }
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
use: {
loader: "babel-loader"
}
},
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: { limit: 10000, name: './images/[name].[ext]' }
}]
},
{
test: /\.(sass|scss)$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
},
performance: {
maxAssetSize: 400000000,
maxEntrypointSize: 400000000,
hints: 'warning'
},
plugins: plugins,
externals: {
jquery: 'jQuery'
}
}
module.exports = config
And my webpack.config.prod.js file:
// PRODUCTION
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const entry = {
app: path.join(process.cwd(), 'src/app.js')
}
const output = {
path: path.join(__dirname, 'dist'),
filename: 'bundle.min.js',
}
const plugins = [
new webpack.DefinePlugin({
// 'process.env.NODE_ENV': JSON.stringify('production')
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
mangle: false,
compress: {
warnings: false
}
}),
new ExtractTextPlugin('bundle.css'), // creation of HTML files to serve your webpack bundles
new HtmlWebpackPlugin({
template: 'index-template.html'
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'bundle',
filename: '[name].common.js'
})
]
const config = {
context: path.join(__dirname, 'src'),
entry: entry,
output: output,
devtool: "source-map",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
use: "babel-loader"
},
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: { limit: 10000, name: './images/[name].[ext]' } // Convert images < 10k to base64 strings (all in images folder)
}]
},
{
test: /\.(sass|scss)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [ require('autoprefixer')() ]
}
},
'sass-loader',
]
})
}
]
},
plugins: plugins,
externals: {
jquery: 'jQuery'
}
}
module.exports = config;
..I know that there are much better ways to do this than to have two menu components that renders on different pages, but I just did this solution for now .. Problem is that I don't understans how to convert this to HashHistory of BrowserHistory without loosing my logic. Any tips/input would be so goddammit appreciated, been sitting with this for weeks now <3
Cannot GET /currentPage ?
For browserHistory on page refresh ,/currentPage is requested on server side.
At the backend, your server dont defined this path (requested resource).
You need to implement it to fixed Cannot GET issue for page refresh.
Assuming nodejs
app.use(express.static(__dirname));
//will serve index.html for every page refresh.
app.use('*',(req,resp)=>{
res.sendFile(path.resolve(__dirname+'/index.html'))
})
app.listen(someport)
This will load index.html page for every page refresh.
Once index.html is loaded with required JS & react router,
the router will trigger the route and corresponding component is getting rendered.
#Panther solved this. To be able to refresh page in my dev environment, I had to add:
historyApiFallback: {
disableDotRule: true
}
to my webpack dev.server file:
var WebpackDevServer = require('webpack-dev-server');
var webpack = require('webpack');
// requiring my webpack configuration
var config = require('./webpack.config.js');
var path = require('path');
var compiler = webpack(config);
// then spinning up a new dev server with some settings
var server = new WebpackDevServer(compiler, {
hot: true,
filename: config.output.filename,
publicPath: config.output.publicPath,
proxy: {
"/getMail": 'http://localhost:80/magdan/php/mailer.php',
"/getProducts": 'http://localhost:80/magdan/php/products.php'
},
stats: {
colors: true
},
historyApiFallback: {
disableDotRule: true
}
});
// its gonna listen to port 8080
server.listen(8080, 'localhost', function() {
console.log("Starting server on http://localhost:8080");
});