多页HTML站点引入React编译组件 非首页加载空白无报错问题
问题原因
核心问题是子路由页面的静态资源使用了相对路径引用,导致资源请求地址完全错误:
- 访问首页时地址为站点根路径
/,HTML中写的<script src="app.js"></script>、<link href="app.css" rel="stylesheet"/>会被浏览器解析为请求根目录下的/app.js、/app.css,刚好和静态资源实际存放路径匹配,因此首页可以正常运行。 - 访问
/blog路由时,页面的URL基准路径变为/blog,同样的相对路径写法会被浏览器自动拼接为/blog/app.js、/blog/app.css两个请求地址,而编译生成的js、css文件根本没有存放在这个路径下,核心资源完全没有加载成功。 - 控制台无报错的原因也很明确:后端大概率配置了单页应用路由兜底规则,所有未匹配到的请求都会返回index.html,此时请求
/blog/app.js拿到的是首页的HTML内容,浏览器将HTML当作JS/CSS解析时不会抛出404类错误,只会静默解析失败,React相关代码压根没有执行,页面自然显示空白。
另外你写的parcel编译命令本身存在逻辑问题:先将parcel编译产物输出到widget目录,后面却从build/static/css路径(这是create-react-app的默认输出路径,不是parcel的输出路径)复制css文件,这个操作本身无法拿到正确的css产物,只是之前可能手动放置过css到根目录,首页才没有出现样式异常。
解决方法
按顺序修改后即可正常加载:
- 将所有子页面(包含blog.html)内的静态资源引用改为根路径绝对引用,在资源路径前增加
/前缀:
修改后无论页面处于哪个路由层级,浏览器都会固定从站点根目录查找资源,不会出现路径拼接错误。<link href="/app.css" rel="stylesheet"/> <script src="/app.js"></script> - 修正parcel编译命令,增加公共路径参数,同时修正css复制的路径错误:
增加"parcel": "parcel build src/index.js --no-minify --no-source-maps --public-url / -d ../build/widget && cp ../build/widget/*.css ../build/app.css"--public-url /参数是为了保证编译后的js文件内部引用的异步模块、静态资源也从根路径开始请求,避免内部资源加载失败。 - 调整后端路由注册顺序,将静态资源中间件放在所有页面路由之前注册,保证js、css、图片这类静态资源请求会被优先处理,不会走到页面兜底逻辑中:
// 优先注册静态资源托管,指定build目录为静态资源根 files_routes.use(express.static('../build')) // 再注册页面路由 files_routes.get('/', (request, response) => { response.sendFile('index.html', { root: '../build' }) }); files_routes.get('/blog', (request, response) => { response.sendFile('blog.html', { root: '../build' }) }); - 修改完成后清除浏览器缓存再访问/blog,打开开发者工具网络面板确认app.js、app.css的请求路径为根路径下的地址,响应内容为正确的js、css代码后,React就会正常将组件渲染到id为app的容器中。
内容的提问来源于stack exchange,提问作者afabei
相关产品推荐
相关产品推荐

