# modules 模块化

# 模块化的优点:

可维护性、可复用性。

# 模块化的发展

1、ES6 之前没有模块化时,浏览器环境需要使用 script 进行引入 js 文件
2、后来使用全局变量 + 命名空间(namespace)处理,就是使用 IIFE 自动执行函数创建一个函数作用域,赋值给一个全局变量。
这样做的缺点是:依赖于全局变量,污染全局变量,不安全。
依赖于约定命名空间来避免冲突,可靠性不高。
需要手动管理依赖并控制执行顺序,容易出错。
需要在最终上线前手动合并所有用到的模块。
3、node 端模块系统:Common.js,缺点是浏览器端无法使用
4、AMD (Asynchronous module definition) 异步加载模块定义,CMD (模块标准)
采用异步方式加载,需要全局环境定义 require 和 define,不需要引入其他的变量。
5、ES6 modules、引入和暴露方式更加多样,支持复杂的静态分析和静态、动态导入。

# Bundler 打包工具

# 诞生原因:

使用 import export 这种异步加载方式在大多数浏览器中无法使用。

# 常见工具

一、Webpack(单 JS 文件入口),Webpack 采用代码分割、异步加载等技术,可以将多个模块打包成一个或者多个 bundle,,构建的产物是一个函数。Webpack 主要用于构建复杂的前端项目,如 Web 应用、SPA 单页面应用等,支持模块化开发、代码分割、资源优化和静态文件处理等功能。。

二、rollup 用静态的方式分析代码,对未使用的代码更加彻底的进行树摇优化,输出的 bundle 更加的精简。

三、snowpack(使用于新版浏览器)
1、出现的原因(其他 Bundler 的问题):
当资源越来越多时,打包的速度会越来越慢,大中型项目中,启动时间可能达到好几分钟。(vite 的理念来源于 snowpack,充分使用了新版浏览器支持 es modules 的特性。)
2、优势:
snowpack 利用新版浏览器支持 es modules 的特性,开发模式不会被打包,每个文件编译一次,永久被缓存,当一个文件修改的时候就只需要重新 build 那一个文件。(适用于新版浏览器)
四、vite
vite 基于 snowpack 的理念(利用新版浏览器支持 es modules 的特性),基于 es-modules,采用 rollup 进行构建 ,开发模式不会打包,每个文件当使用时才会去加载,修改时只需要重新 build 那一个文件。
五、vue-cli
vue-cli 底层基于 webpack,webpack 通过导入导出的语句分析整个项目,将目标代码转化成兼容浏览器的 js 代码,只有打包后的几个文件,这个过程需要耗费一些时间。

# webpack 配置支持 ES Module

webpack 默认只支持 CommonJS 规范,配置支持 ES Module 规范,需要进行如下配置:
一:将 ES Module 语法的 js 文件通过 webpack 进行打包即可。
二:webpack 默认 target 为 web,在使用 node 内置库时会报错,可以修改 target 属性。

const path = require('path');
module.exports = {
    entry: './bin/core.js',
    output: {
        path:path.join(__dirname,'/dist'),
        filename: 'core.js',
    },
    mode: 'production', // 改变打包模式
    target: 'node' // 进入 node 环境,默认是 web
}

三、webpack 配置 babel-loader,兼容低版本 node
方案一:安装 babel-loader、@babel/core、@babel/preset-env(有时需要 @babel/plugin-transform-runtime 插件)

const path = require('path');
module.exports = {
    entry: './bin/core.js',
    output: {
        path:path.join(__dirname,'/dist'),
        filename: 'core.js',
    },
    mode: 'production', // 改变打包模式
    target: 'node', // 进入 node 环境,默认是 web
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',  // 使用 babel-loader
                    options: {
                        presets: ['@babel/preset-env'],
                        plugins:[
                            [
                                '@babel/plugin-transform-runtime',
                                {
                                    corejs: 3,
                                    regenerator: true,
                                    useESModules: true,
                                    helpers: true,
                                },
                            ],
                        ]
                    },
                }
            }
        ]
    }
}

方案二:node.js 实验功能
将 js 后缀更改为 mjs 后缀,即可(需要 node 版本为 14 以上), 小于 14 版本的时候,node 执行时需要加上 --experimental-modules 参数,例如:
node --experimental-modules index.js

# npm

# 冷知识

npm dedupe 命令

该命令用于去重依赖和优化依赖树, npm dedupe 命令会检查 node_modules 中的依赖树,并尝试将公共依赖上移,以减少冗余的副本,优化依赖树
package-lock.json 文件
默认的 package.json 文件中存在依赖版本兼容,导致后续依赖包升级或某些其他情况下,每一个环境中执行 npm install 命令时,安装的依赖版本不同,这时候就有了 package-lock.json 文件,它可以精确锁定版本号和依赖,并存储仓库地址信息,使得依赖安装更快.
最佳的实践方式是:把 package-lock.json 一起提交到代码库中,不需要 ignore。但是执行 npm publish 命令,发布一个库的时候,它应该被忽略而不是直接发布出去 (库项目一般是给其他仓库安装使用,不使用 lock 文件就可以复用主项目加载过的包)。
npm ci 命令
npm ci 命令会完全根据 package-lock.json 安装依赖,这可以保证整个开发团队都使用版本完全一致的依赖;执行 npm ci 时,会先删除项目中所有的 node_modules 再安装. npm ci 永远不会改变 package.jsonpackage-lock.json 文件
依赖是否出现在最终打包后的代码中取决于该依赖是否被引用
devDependencies 开发依赖
用于指定生产依赖,该依赖不会被自动加载 (被别的模块依赖时)
并不是只有在 dependencies 中的模块才会被一起打包,而在 devDependencies 中的依赖一定不会被打包。实际上,依赖是否被打包,完全取决于项目里是否被引入了该模块。dependencies 和 devDependencies 在业务中更多的只是一个规范作用,我们自己的应用项目中,使用 npm install 命令安装依赖时,dependencies 和 devDependencies 内容都会被下载。
peerDependencies 对等依赖
用于指定依赖于某些三方模块作为基础 (被别的模块进行加载时)
peerDependencies 主要意义在于声明该模块无法脱离某个三方模块单独存在,而如果放在 devDependencies 字段中就无法共享主模块中已下载的三方模块
使用场景有:插件不能单独运行,插件正确运行的前提是核心依赖库必须先下载安装,不希望核心依赖库被重复下载 等
npm pack 打包命令
npm pack 命令可以根据 package.json 中的 bundledDependencies 字段和其他信息,将当前仓库打包为一个.tgz 格式的压缩文件,在发布到 npm 仓库之前可以用于本地功能测试、单文件离线下载、包的分发 (离线分发给团队成员使用) 等
通过 npm 安装此 tgz 包可以使用 npm install package_name-1.0.0.tgz 来安装 tgz 包
bundledDependencies 打包依赖
bundledDependencies 打包依赖字段会被 npm pack 命令所使用,当执行 npm pack 命令时,会根据此字段将项目打包为几个模块 tgz 包.

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

dmq 微信支付

微信支付

dmq 支付宝

支付宝