chikara-chan / react-isomorphic-boilerplate

🌟 An universal React isomorphic boilerplate for building server-side render web app.
https://chikara-chan.github.io/react-isomorphic-boilerplate/
MIT License
652 stars 148 forks source link

server/middlewares/clientRoute.js中路由匹配match()函数问题前是否要加await操作符? #8

Open sivkun opened 7 years ago

sivkun commented 7 years ago

match({routes,location:ctx.url},(error,redirectLocation,renderProps)=>{ _renderProps=renderProps }) 改为: await match({routes,location:ctx.url},(error,redirectLocation,renderProps)=>{ _renderProps=renderProps }) 我使用你个这脚手架,学习开发一个小项目,运行npm run dev ,浏览器可以正常访问。 但是构建后,执行npm start,页面提示Not found! 经过调试发现,在match函数回调中为_renderProps赋值。在match返回前继续往下运行,提示not found。 奇怪的是开发模式下正常,这是为什么呢?

chikara-chan commented 7 years ago

await关键字后面跟的只能是一个Promise对象

sivkun commented 7 years ago

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/await,如果这个值不是一个 promise,那么会把它转换成一个已经 resolved 的 promise,并且等待它。这里match确实是异步的,_renderProps在回调中被赋值,在赋值前,程序如果继续往下执行,会出问题啊。这个项目,没有出现问题,但是我用这个框架做一个demo时,确实出了问题。

chikara-chan commented 7 years ago

match本身是一个同步方法,不涉及网络请求与文件操作,可以在代码match函数内外console.log查看执行顺序

chikara-chan commented 7 years ago

方便上传项目源码吗

sivkun commented 7 years ago

我就是用console.log发现的这个问题。很奇怪的是,在dev模式没有这个问题。源码在这https://github.com/sivkun/myplayer-isomorphic。

chikara-chan commented 7 years ago

https://github.com/ReactTraining/react-router/issues/4677 产生原因:webpack2与webpack1对require.ensure的打包机制处理方式不同

sivkun commented 7 years ago

谢谢,我看一下

chikara-chan commented 7 years ago

审查webpack打包后的代码,可以看到 webpack1中require.ensure原型是

/******/    __webpack_require__.e = function requireEnsure(chunkId, callback) {
/******/        // "1" is the signal for "already loaded"
/******/        if(!installedChunks[chunkId]) {
/******/            var chunk = require("./chunk." + ({"1":"home","2":"explore","3":"about"}[chunkId]||chunkId) + ".js");
/******/            var moreModules = chunk.modules, chunkIds = chunk.ids;
/******/            for(var moduleId in moreModules) {
/******/                var _m = moreModules[moduleId];

/******/                // Check if module is deduplicated
/******/                switch(typeof _m) {
/******/                case "object":
/******/                    // Module can be created from a template
/******/                    modules[moduleId] = (function(_m) {
/******/                        var args = _m.slice(1), templateId = _m[0];
/******/                        return function (a,b,c) {
/******/                            modules[templateId].apply(this, [a,b,c].concat(args));
/******/                        };
/******/                    }(_m));
/******/                    break;
/******/                case "function":
/******/                    // Normal module
/******/                    modules[moduleId] = _m;
/******/                    break;
/******/                default:
/******/                    // Module is a copy of another module
/******/                    modules[moduleId] = modules[_m];
/******/                    break;
/******/                }
/******/            }
/******/            for(var i = 0; i < chunkIds.length; i++)
/******/                installedChunks[chunkIds[i]] = 1;
/******/        }
/******/        callback.call(null, __webpack_require__);
/******/    };

webpack2的require.ensure原型是

/******/    __webpack_require__.e = function requireEnsure(chunkId) {
/******/        // "0" is the signal for "already loaded"
/******/        if(installedChunks[chunkId] !== 0) {
/******/            var chunk = require("./" + chunkId + ".bundle.js");
/******/            var moreModules = chunk.modules, chunkIds = chunk.ids;
/******/            for(var moduleId in moreModules) {
/******/                modules[moduleId] = moreModules[moduleId];
/******/            }
/******/            for(var i = 0; i < chunkIds.length; i++)
/******/                installedChunks[chunkIds[i]] = 0;
/******/        }
/******/        return Promise.resolve();
/******/    };

webpack1直接调用回调函数,webpack2返回的是个promise

kevin-love commented 7 years ago

我也遇到了上面的问题,但我改为一下: if(typeof require.ensure !=='function'){ require.ensure = function(dependencies,callback){ setTimeout(function() { callback(require) });
} }

还是无法解决,match的回调还是后执行,不知道有没有其他方法呢~谢谢