zoukankan      html  css  js  c++  java
  • Node.js + Webpack5 后端开发 构建自动重载服务器

    Webpack5的变化

    1. 前端开发变化, 开箱即用webpack serve命令,只需要安装webpack-dev-server就可以直接启用了。
    $ webpack serve --help
    Usage: webpack s | serve
    Description: Run the webpack Dev Server
    

    此时,npx webpack-dev-server命令会报错,因此它只兼容Webpack4,不过Webpack5可以使用它(webpack serve命令就是调用它):

    $ npx webpack-dev-server
    Cannot find module 'webpack-cli/bin/config-yargs'
    Require stack:
    - C:UserslyDesktopTypeScript
    ode_moduleswebpack-dev-serverinwebpack-dev-server.js
    

    webpack-node-externals库

    使用Webpack开发后端时,通常不希望捆绑node_modules下的依赖项。该库创建了一个外部函数,使Webpack中捆绑时将忽略node_modules下的模块。
    Github:https://github.com/liady/webpack-node-externals
    安装:

    npm install webpack-node-externals -D
    yarn add webpack-node-externals -D
    

    原理:externals作为一个函数使用 -- https://webpack.js.org/configuration/externals/#function

            externals: [
                // 'express',
                function ({ context, request }, callback) { // 官网和CLI提示不一致,此处遵循CLI标准
                    console.log(`${context} => ${request}`); // 打印import和require请求
                    callback(); // 通过请求
                },
            ],
    

    例子:该函数过滤express模块,该模块的导出语句直接替换为require('express')

                function ({ context, request }, callback) {
                    if (!context.match(/.*node_modules.*/)) {
                        console.log(`请求:${context} => ${request}`);
                        if (request === 'express') {
                            callback(null, `require('express')`); // 直接编码`const express = ?`赋值语句的右值
                        } else {
                            callback();
                        }
                    } else {
                        console.log(`其它:${context} => ${request}`);
                        callback();
                    }
                },
    

    该怎么实现webpack-node-externals库的功能呢?

    观察发现express导致了更多的require请求,这些请求的上下文都是在node_modules目录下,但是不能拒绝这些请求,否则无法生存dist:

                        console.log(`其它:${context} => ${request}`);
                        // callback(); 忽略请求,编译被中断
    


    其实,对于node_modules目录下的请求,使用require('${contextByNode_Modules}/${request}')语句是可以减轻编译重量的:

            externals: [
                // 'express',
                function ({ context, request }, callback) { // 官网和CLI提示不一致,此处遵循CLI标准
                    if (!context.match(/.*node_modules.*/)) {
                        console.log(`导入:${context} => ${request}`);
                        callback();
                    } else {
                        let contextByNode_Modules = context.match(/.*node_modules[/\](.*)$/)[1];
                        console.log(`其它:${context} => ${request}`);
                        let cmd = `require('${contextByNode_Modules}/${request}')`;
                        console.log({ cmd });
                        callback(null, cmd);
                    }
                },
            ],
    

    但是这些模块还是被Webpack解析了(例中的express),并且被部分绑定(哭),达不到“由宿主提供提供该库”的要求。

    相对合理的解决方案

                function ({ context, request }, callback) { // 官网和CLI提示不一致,此处遵循CLI标准
                    console.log(`导入:${context} => ${request}`);
                    // return callback(); // 临时关闭函数以测试
                    // 排除node_modules模块以及loader
                    if (!path.isAbsolute(request) && !request.match(/^./)) { // require目标不是绝对路径,且不以dot开头,则大概率就是node_modules请求。
                        // 要排除入口,直接遍历config.entry字段似乎不太可行,因为有隐含规则,比如"./src/index.js"。
                        // 上下文不可以是cwd,或者__dirname,从而排除入口(此处担心入口是绝对路径,且不以dot开头,这样会造成编译完成但运行时找不到模块)
                        if (context !== process.pwd && context !== __dirname) {
                            // 还有一种情况:在import或require语句中指定了loader,而指定方式又有强制与非强制的区别。
                            // 一般来说,即便这些依赖项可以在运行时加载,不过我们也希望进行编译打包,从而方便开发
                            // 如果指定了loader,则一定含有感叹号!这种情况需要排除掉
                            if (!request.includes('!')) {
                                // 替换node_modules依赖请求
                                let instruction = `require('${request}')`;
                                console.log('运行时依赖:', `${request}由node_modules提供 => ${request} = ${instruction}`.green);
                                return callback(/*没有错误*/null, instruction);
                            }
                        }
                    }
                    return callback();
                },
    

    自动重载以应用代码更新

    Github: https://github.com/develon2015/node-dev-server
    想必大家都知道前端开发工具: webpack-dev-server, 本人实现了一个类似的功能, 不过它在后端开发中发挥作用!

    值得一提的是,@nest/cli也是使用的webpack实现,并且也使用了第三方开源库设置externals来排除node_modules模块。

  • 相关阅读:
    【NOIP】提高组2015 运输计划
    【BZOJ】1635: [Usaco2007 Jan]Tallest Cow 最高的牛
    【51nod】1766 树上的最远点对
    【BZOJ】2054: 疯狂的馒头
    【SRM20】数学场
    【Luogu】P3930 SAC E#1
    【Luogu】P3927 SAC E#1
    【Luogu】 P3928 SAC E#1
    【Codeforces】868C. Qualification Rounds
    【CodeForces】866D. Buy Low Sell High
  • 原文地址:https://www.cnblogs.com/develon/p/13852019.html
Copyright © 2011-2022 走看看