TypeError: load is not a function
good-idea opened this issue · 6 comments
I'm having trouble with some universal components not loading when they are first requested. They need to fail once (showing the NotFound component), then be requested a second time to work.
TypeError: load is not a function
at requireUniversalModule.js:93
at new Promise (<anonymous>)
at requireAsync (requireUniversalModule.js:69)
at ProxyComponent.requireAsync (index.js:280)
at ProxyComponent.requireAsync (react-hot-loader.development.js:693)
at ProxyComponent.componentWillReceiveProps (index.js:244)
at callComponentWillReceiveProps (react-dom.development.js:12564)
at updateClassInstance (react-dom.development.js:12774)
at updateClassComponent (react-dom.development.js:14262)
at beginWork (react-dom.development.js:15082)
I'm using the same <UniversalComponent />
that is in the universal-demo repo. My main App looks like this:
const App = () => (
<Outer>
<Router>
<Homepage path="/" />
<UniversalComponent path="/page-a" page="PageA" minDelay={1200} />
<UniversalComponent path="/page-b" page="PageB" minDelay={1200} />
</Router>
</Outer>
)
- I visit
/page-a
- I click a
<Link />
to/page-b
- UniversalComponent renders my NotFound component, with the error supplied in the props
- I navigate back to
/page-a
- I click the same
<Link />
to/page-b
- UniversalComponent successfully fetches and renders the page, as expected.
(I'm using @reach/router, not sure if this is relevant)
If I add a console.log(config)
on line 34 of the bundled dist/requireUniversalModule.js
:
var config = getConfig(isDynamic, universalConfig, options, props);
var chunkName = config.chunkName,
path = config.path,
resolve = config.resolve,
load = config.load;
console.log(config)
config
is never supplied with a load
function.
Is there anything obvious I might be missing? I'm not sure where to start debugging this. The code is in a client project so I can't share right now - but if this is a difficult problem I can make a stripped down repo.
webpack/client.local.js
module.exports = { name: 'client', target: 'web', devtool: 'inline-source-map', mode: 'development', entry: [ '@babel/polyfill', 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=false&quiet=false&noInfo=false', 'react-hot-loader/patch', path.resolve(__dirname, '../src/client/index.js'), ], output: { filename: '[name].js', chunkFilename: '[name].js', path: path.resolve(__dirname, '../build/client'), publicPath: '/public/', }, resolve: { symlinks: false, alias: { Components: path.resolve(__dirname, 'src', 'client', 'Components'), Views: path.resolve(__dirname, 'src', 'client', 'Views'), Utils: path.resolve(__dirname, 'src', 'client', 'Utils'), Types: path.resolve(__dirname, 'src', 'client', 'Types'), 'test-utils': path.resolve(__dirname, 'src', 'client', 'Types'), }, extensions: ['.js'], },module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', }, ], }, { test: /\.svg$/, use: [ { loader: 'babel-loader', }, { loader: 'react-svg-loader', options: { jsx: true, // true outputs JSX tags }, }, ], }, ], }, plugins: [ new WriteFilePlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin(), new webpack.DefinePlugin({ 'process.env': { IS_SSR: true, NODE_ENV: JSON.stringify('development'), }, }), ],
}
webpack/server.local.js
const config = { name: 'server', devtool: 'source-map', target: 'node', // node: { // __dirname: false, // }, resolve: { symlinks: false, alias: { Components: path.resolve(__dirname, 'src', 'client', 'Components'), Views: path.resolve(__dirname, 'src', 'client', 'Views'), Utils: path.resolve(__dirname, 'src', 'client', 'Utils'), Types: path.resolve(__dirname, 'src', 'client', 'Types'), 'test-utils': path.resolve(__dirname, 'src', 'client', 'Types'), }, extensions: ['.js'], },module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', }, ], }, { test: /\.svg$/, use: [ { loader: 'babel-loader', }, { loader: 'react-svg-loader', options: { jsx: true, // true outputs JSX tags }, }, ], }, ], }, mode: 'development', entry: ['regenerator-runtime/runtime.js', entry], externals, output: { path: output, filename: '[name].js', libraryTarget: 'commonjs2', }, plugins: [ new WriteFilePlugin(), new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1, }), new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('development'), }, }), ],
}
.babelrc
module.exports = { presets: [ '@babel/preset-flow', [ '@babel/preset-env', { modules: false, targets: { browsers: ['last 3 versions'], }, }, ], '@babel/preset-react', ], env: { development: { plugins: ['flow-react-proptypes'], }, test: { presets: [ [ '@babel/preset-env', { modules: 'commonjs', }, ], ], }, }, plugins: [ 'universal-import', 'babel-plugin-styled-components', [ 'babel-plugin-module-resolver', { root: ['./'], alias: { Components: './src/client/Components', Views: './src/client/Views', Utils: './src/client/Utils', Types: './src/client/Types', Services: './src/client/services', Queries: './src/client/Queries', 'test-utils': './jest/test-utils.js', }, }, ], '@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread', '@babel/plugin-proposal-export-default-from', '@babel/plugin-syntax-dynamic-import', 'react-hot-loader/babel', 'lodash', 'ramda', ], }
If I do:
import './PageA'
import './PageB'
at the top of App.js, it works. But, of course, it means these modules are not split out into separate chunks. (I think?)
OK, I got this working. I'm not sure what was different about my setup that caused the problem in the first place. The fix was changing determineHowToLoad
, from:
const determineHowToLoad = props =>
Promise.all([
import(/* webpackChunkName: '[request]' */ `./${props.page}`)
]).then(proms => proms[0])
to simply:
const determineHowToLoad = (props) => import(`./${props.page}`)
referencing: https://github.com/faceyspacey/universal-demo/blob/master/src/client/UniversalComponent.tsx#L9
I first I would start with using the <Component page={()=>import()}/>
Rather than strings. Honestly I never use strings anymore because resolving stuff is a nightmare
Lol as I read thru I see you came to the conclusion. Check out the RFR demo or look under my profile for a repo called Icarus. Then find the UniversalComponent.js file
Your implementation is correct but you might be able to just paste the one I use in and get nice results. Are you using our Babel plugin?
Yes, I'm using the plugin. I like the string-or-import option in your Icarus <UniversalComponent />
.
Right now the only components I'm importing are in one directory (/Views
), but I'll be digging back in soon to get smarter about how I'm splitting everything up.
Thanks for the quick response, and for a great utility!
its been a tough journey and we have faced some hardships, being the worlds first developers to bring this to market. It means a lot that so many still use our work.
Please let me know your progress and I’m willing to poersonally help my dependents. You get stuck - hit me up with a repo. Ive seen 100s if not 1000s of repos by now and know near everything that can go wrong
I cloned universal demo and tried to implement routes.js and I got same error.
const determineHowToLoad = ({ page }) =>
typeof page !== "string" ? () => page() : import(`../pages/${page}/${page}`);
const UniversalComponent = universal(
(props) => import(`../pages/${props.page}/${props.page}`),
{
onLoad: () => {
console.log("somethign");
},
}
);
When I switched to this
const determineHowToLoad = (props) => import(
./${props.page})
error is gone but I cannot navigate. any endpoint only shows the homepage.
export const indexFromPath = (path) => { path = path === "/" ? "/HomePage" : path; //path starts with "/" so we omit it return pages.indexOf(path.substr(1)); };
I could not figure out how to implement routes with using universal component. It is a great a package and i wanna fully learn it.
Also onLoad function is not working :(
Thank You!