zoukankan      html  css  js  c++  java
  • webpack高级概念,webpack-dev-server解决单页面应用路由问题(手动搭建webpack,不是用脚手架,404找不到页面,一)(系列十五)

    目前比较主流的框架如Vue、React等,都是单页面应用的框架。一般我们在使用它们的时候,会使用官方脚手架来创建项目,所以我们不必关心单页面应用路由是如何实现的,因为脚手架中已经帮我们做好了配置。在具体项目开发中,我们只需要做相应的路由配置即可。

    那么在实际项目中,手动搭建项目的前提下,我们需要如何解决单页面应用的路由问题呢???

    看个?:
    目录结构:

    |--demo
        |--src
            |--index.html
            |--index.js
            |--home.js
            |--list.js
        |--node_modules
        |--.babelrc
        |--package-lock.json
        |--package.json
        |--webpack.config.js
    

    webpack.config.js中的配置:

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    const webpack = require('webpack');
    
    module.exports = {
      mode: 'development',
      devtool: 'cheap-module-eval-source-map',
      entry: {
        main: './src/index.js'
      },
      devServer: {
        contentBase: './dist',
        open: true,
        port: 8081,
        hot: true,
        hotOnly: true
      },
      module: { 
        rules: [{
          test: /.js$/,
          loader: 'babel-loader',
          exclude: /node_modules/
        }]
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: './src/index.html'
        }),
        new CleanWebpackPlugin(),
        new webpack.HotModuleReplacementPlugin()
      ],
      output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
      }
    }
    


    .babelrc配置:

    {
      "presets": [
        [
          "@babel/preset-env", {
            "targets": {
              "chrome": "67"
            },
            "useBuiltIns": "usage"
          }
        ],
        "@babel/preset-react"
      ]
    }
    


    package.json中scripts配置:

    "scripts": {
        "start": "webpack-dev-server"
    }

    index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>html template</title>
      </head>
      <body>
        <div id='root'></div>
      </body>
    </html>


    src/index.js:

    import React, { Component } from 'react';
    import { BrowserRouter, Route } from 'react-router-dom'; // 引入路由模块
    import ReactDom from 'react-dom';
    import Home from './home.js';
    import List from './list.js';
    
    // 这里设置的路由,根据用户的请求,来决定展示什么
    class App extends Component {
      render() {
        return (
          <BrowserRouter>
            <div>
              <Route path='/' exact component={ Home } />
              <Route path='/list' component={ List } />
            </div>
          </BrowserRouter> 
        )
      }
    } 
    
    ReactDom.render(<App />, document.getElementById('root'));
    

    期望效果:

    当用户访问根路径时,会访问home组件的内容
    当用户访问/list路径时,会访问list组件的内容
    src/home.js:

    import React, { Component } from 'react';
    
    class Home extends Component { 
      render() {
        return <div>HomePage</div>
      }
    } 
    
    export default Home;
    

    src/list.js:

    import React, { Component } from 'react';
    
    class List extends Component {
      render() {
        return <div>ListPage</div>
      }
    } 
    
    export default List;
    

    注: 记得通过npm包管理工具一一安装上方所有配置项中的依赖、插件以及第三方库。

    执行打包:

    npm run start

    唤起浏览器localhost:8081服务:

    当访问"/list"路由时(访问的是后台路由),我们期望出现ListPage的内容,但是实际情况如下:

    注: 当我们去访问localhost:8081/list这个地址的时候,webpackDevServer会默认为你要访问服务器上的一个list页面。但我们的项目中只有一个index.html页面(打包后的),并不存在list页面(后端的一个list页面)。所以它会提示你:Cannot GET /list (页面不存在)

    我们可以使用webpackDevServer中的 historyApiFallback 配置来解决此问题:打开webpack官网。 https://webpack.js.org/configuration/dev-server#devserverhistoryapifallback

    devServer: {
        contentBase: './dist',
        open: true,
        port: 8081,
        hot: true,
        hotOnly: true,
        historyApiFallback: true // 在使用单页面应用的时候,需要设置此参数,代表如果访问除根路径以外的地址,最终都会转向去请求根路径。
    },
    


    historyApiFallback: true 代表在使用单页面应用的时候,需要设置此参数,代表如果访问除根路径以外的地址,最终都会转向去请求根路径。

    他的原理是后端服务器如果发现并没有这个/list地址。就会偷摸的转化成根路径的请求,所以不管请求什么地址,都会请求index.html,里面有main.js,也就是我们的业务代码,这里面的路由就能正常的生效。
    此时再执行打包:

    npm run start

    浏览器显示正常:

    打开控制台网络项:

    从 “/list” 路由请求的响应信息我们可以看出,当访问localhost:8081/list地址时,最终访问的仍然是index.html页面。到此,单页面应用路由问题已完美解决。
    所以,当我们在使用单页面应用时,记得一定要在devServer中配置historyApiFallback: true配置项。

    historyApiFallback 的详细配置

    historyApiFallback: {
          rewrites: [
            { from: /abc.html/, to: '/index.html' }
          ]
    }


    rewrites 中的配置代表:当我访问locahost:8081/abc.html时,devServer会自动帮我们转向访问index.html页面。
    from 指访问的地址
    to 指devServer最终帮我们转向的地址
    以上面例子中的 historyApiFallback:true 也就等价于:

    historyApiFallback: {
          rewrites: [
            { 
                from: /.*/,  // 访问任何地址
                to: '/index.html'  // 都转向index.html页面(根路径页面)
            }
          ]
    }
    

    一般的项目中,当我们做单页面应用,配置单页面路由时,设置 historyApiFallback:true;即可解决。

    注: historyApiFallback只是在我们的开发环境中(本地)有效,一旦代码上线,就会再次出现访问页面找不到的问题。这时就需要后端小伙伴配合,仿照webpack-dev-server的配置,在nginx或apache对应的服务器上做它的一些配置,再进行访问。

    原文链接:https://blog.csdn.net/riona_cheng/article/details/100660065

  • 相关阅读:
    tensorrt 中的一些基本概念 Logger, Context, Engine, Builder, Network, Parser 知识梳理
    JavaWeb之互联网通信流程
    JSON
    JS之BOM编程History和location对象
    JS之将当前窗口设置为顶级窗口
    JS之BOM编程--弹出消息框和确认框
    JS之BOM编程window的open和close
    JS之内置支持类Array
    多次使用setInterval方法导致clearInterval不能成功关闭
    JS之周期函数setInterval
  • 原文地址:https://www.cnblogs.com/fsg6/p/14494065.html
Copyright © 2011-2022 走看看