本地开发服务器

1. 学习要点

  • 分析本地开发服务器解决了哪些问题
  • 动态构建功能的设计和实现
  • Mock服务的设计与实现

2. 本地开发服务器解决的问题

  • 动态构建

    通过监听-> 修改 -> 触发 -> 构建的流程避免了源代码的每次修改都要认为的执行一次构建,便于开发过程中的调试。

  • Mock服务

    前后端开发人员在正式进入开发之前协商好数据接口的规范,前端通过Mock服务模拟请求数据,达到前后端并行开发。

    如果你对项目仍需要依赖服务器端渲染HTML,并且本地开发服务器使用与服务器端相同的编程语言,那么MOCK服务需要具备SSR功能

    1. 支持与服务器端相同的HTML模板

    2. SSR所需的Mock数据

3. 动态构建

webpack-dev-server是官方提供的搭建本地开发环境的一个微型Node.js服务框架,提供了 动态编译,HMR(热更新)等功能。但是它不包含Mock服务。webpack还提供了一个webpack-dev-middleware 他是Express框架的一个中间件,结合一些必要的功能模块可以实现动态编译以及热更新

webpack-dev-middleware 将webpack构建输出的文件存储在内存中。 我们利用express和 webpack-dev-middleware封装一个类似webpack-dev-server的本地开发服务器,但是它要包含Mock服务。 需要解决两点问题 :

  1. 如何启用对源文件的监听并处罚动态编译
  2. 如何令客户端可访问有HTML引用但是并未参与构建的本地静态文件?比如Jquery等第三方库,这类文件由script标签引入,不参与webpack构建。
    const Express = require('express');
    const WebPackDevMiddleware = require('webpack-dev-middleware');
    const App = Express();
    const Webpack = require('webpack');
    const WebpackCompiler = Webpack(WebpackConf);
    App.use(WebPackDevMiddleware(WebpackCompiler));

  • 启用监听

    webpack-dev-middleware的配置可以实现监听和触发动态编译

    • lazy -- 是否开启惰性模式
    • watchOptions -- 监听细节配置 arraegateTimeout 指定webpack的执行频率,单位为毫秒 (300) ignored 指定不参与监听的文件 poll 指定webpack监听无效时轮训校验文件的频率,单位为毫秒。 是无法监听文件变化的情况下去主动轮训查看的备选方案。
  • 静态资源服务 在开发中一些常用的第三方库使用单独的script或者link标签引入,不参与构建,只能借助Express内置的static中间件将这些文件作为讲台内容开发给HTTP服务。

  // 综上所属
    const Express = require('express');
    const Webpack = require('webpack');
    const WebPackDevMiddleware = require('webpack-dev-middleware');
    const App = Express();

    const WebpackCompiler = Webpack();
    App.use('/libs',Express.static(Path.join(process.cwd(),'static')))
        .use(WebPackDevMiddleware(WebpackCompiler,{
            lazy:false,
            watchOptions:{
                aggregateTimeout:300,
                ignored:/node_modules/,
                poll:false
            }
        }));

    App.listen(8080,err => {
        if(err){
            throw new Error(err)
        }
    });

那何时刷新页面获取编译后的文件呢? Livereload 和 HMR

  • Livereload 是在浏览器和服务器之间创建一个Websocket连接,服务端在执行完动态编译后发送reload事件至浏览器,浏览器接收到事件后调用刷新。它的致命缺点是 刷新页面后 浏览器的当前内容状态无法保存。

  • HMR 是在webpack向构建输出的文件中注入了一个额外的功能模块 HMR Runtime。同时在服务端也注入了对应的服务模块 HMR Server 两者是客户端与服务端的关系。也是通过Websocket连接通信。HMR Runtime通过部分更新的形式 不刷新啊浏览器达到更新效果。

Express集成HMR功能:使用 webpack-hot-middleware中间件。 代码如下

    const Express = require('express');
    const Webpack = require('webpack');
    const WebPackDevMiddleware = require('webpack-dev-middleware');
    const WebPackHotMiddleware = require('webpack-hot-middleware');
    const App = Express();

    const WebpackCompiler = Webpack();
    App.use('/libs',Express.static(Path.join(process.cwd(),'static')))
        .use(WebPackDevMiddleware(WebpackCompiler,{
            lazy:false,
            watchOptions:{
                aggregateTimeout:300,
                ignored:/node_modules/,
                poll:false
            }
        }))
        .use(WebPackHotMiddleware(WebpackCompiler));

    App.listen(8080,err => {
        if(err){
            throw new Error(err)
        }
    });

实现HMR不仅仅需要服务端,客户端也要构建时注入HMR Runtime

    entry:{
        'main.app':[
            'webpack-hot-middleware/client',
            './js/main.app.js
        ]
    },
    plugins:[
        new webpack.HotModuleReplacementPlugin() 
    ]

4. Mock服务

  1. 假数据:在代码中直接使用变量保存假数据代替请求数据。弊端是产生了大量的垃圾代码和注释,另外无法模拟访问请求的异常处理

  2. 客户端Mock: Mock.js 他是通过前端拦截请求实现的。缺点是仍然要在前端业务代码中增加Mock相关代码

  3. Mock Server:本质上是一个简化的Web server

    • 异步数据接口

    Local----本地模式,使用本地JSON数据作为异步接口的请求响应。通过路由实现 Proxy----代理模式,将异步接口代理到线上的其他接口地址。(通过express-http-proxy实现HTTP请求代理)的)