1-1.模块化
复杂的项目拆分成简单的模块
1-2.模块化需要解决的问题以及方案
问题:独立作用域;
早期方案(模块化之前的方案):
a.定义一个全局对象,将属性和方法挂载在全局对象上
b.立即执行函数: 将代码包裹到匿名函数中并调用,有了独立的函数作用域
模块化方案(模块化规范):
CommonJs规范(同步加载,无法实现异步按需加载,会导致运行卡死,不适用于浏览器,适用node运行环境):
module.exports = moduleA
exports.add = function(){}
require('./moduleA')
// 因为有缓存的功能,所以同一个模块多次导入,不会重复加载;
// 按照模块依赖关系,控制加载顺序
// 递归同步加载
AMD规范(浏览器运行环境):
define('模块名',[/*依赖模块列表*/], function(/*依赖模块导出结果*/){
return module // 导出本模块的内容
})
require([/*依赖模块列表*/], function(/*依赖模块导出结果*/){
// 依赖加载完成后的回调函数
})
需要引入第三方库支持(requirejs)
ES Mudule 规范:
导出:
export function hello(){}
export default {}
导入:
import {readFile} from 'fs'
import React from 'react'
三者的区别:
CommonJs:运行时加载,同步加载执行模块,能通过动态语句导出
AMD:运行时加载,优先异步加载依赖,在执行模块回调,能通过动态语句导出
ES6 Module:静态加载,编译时创建依赖引用,加载完即执行模块,不能通过动态语句导出,
2-1 webpack的介绍
将项目模块化时拆解的模块进行合并,只能用于采用了模块化开发的项目。
2-2 webpack的安装
安装环境:webpack5要求系统安装8.0.0及以上版本的Node
安装到全局的方式:npm i -g webpack webpack-cli
安装到本项目的方式:npm install --save-dev webpack webpack-cli
2-3 webpack的运行
在package.json 中配置scripts
"scripts": {
"build": "webpack"
}
(1)命令行参数(优先级高)
"scripts": {
"build": "webpack --mode development"
}
(2) 配置文件(更加灵活)(推荐)
webpack会默认读取项目根目录下(webpack.config.js)中的信息
module.exports = {
mode: env, // 构建模式
entry: './src/index.js', // 入口
output: { // 输出
},
module: {
rules: [{// loader配置
}]
},
plugins: [ // plugin配置
],
resolve: {// 模块解析配置
},
externals: { // 外部扩展配置
}
}
mode: 构建时告知webpack使用相应模式的内置优化,
支持development(开发模式), production(生产模式),none(不使用任何默认优化选项)
entry: webpack以entry为入口,递归找出所有依赖的模块,构建bundle
entry值的类型:
单个入口: string | Array<string>
多个入口: {
[ChunkName: string]: string | Array<string>
}
module:模块转换与模块解析由module设置
wepack原生支持模块:javascript,json,Assets,WebAssembly
非原生支持的模块:CoffeeScript,TypeScript,Sass,Less(需要loader转换)
module中rules属性的配置,决定如何转换不同类型的模块。
module:{
rules: [{
include: /src/
exclude: /src\/add/
test: /\.css$/
resource: ''
}]
}
include: 引入include中匹配的模块,与exclude和resource 不能同时设置
exclude: 排除exclude中匹配的模块,与include与resoucre不能同时设置
test: 模块匹配路径test,与resource不能同时设置
resource: 模块路径,与test不能同时设置
模块转化默认只支持javascript,所以对资源类型的转换,需要加type,用来设置原生支持的模块类型。与loader不能同时使用
示例: require('./a.jpg')
module: {
rules: [{
test: /\.jpg/,
type: 'assets/resource'
}]
}
loader: 将非原生模块转化为Javascript模块,可以使webpack支持多种语言和预处理器的语法编写模块。执行顺序: 从下到上,从右到左。
module: {
rules: [{
test: /\.css$/,
exclude: /(node_modules)/,
use: [
{loader: 'css-loader'},
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [
require('autoprefixer')()
]
}
}
]
}]
}
resolve配置: 告诉webpack怎么查找模块
resolve: {// 模块解析配置
extensions: ['.js', '.ts', '.css', '.scss', '.json'], // 如果require引入的文件没有加后缀名,则使用extensions中的先后顺序进行解析
alias: {// 创建别名
'@': './src'
}
}
插件Plugins:
用于扩展webpack的功能,对于loader不能实现的扩展功能,可以使用webpack Plugin实现。
比如,将依赖的css模块打包到单独文件配置:
plugins:[
new MiniCssExtractPlugin({
// 配置编译后的css路径和文件名,相对于output里的path选项
filename: 'css/[name].css'
})
]
(Plugins配置项接收一个数组,数组中的每一项都是一个要使用的plugin的实例)
output:指示webpack如何去输出,以及在哪里输出你的[bundle/assets/其他使用webpack载入的任何内容]
output: {
// 文件输出到哪个目录
path: path.join(__dirname, '../src/dist')
// 输出的合成文件的文件名
filename: 'main.js',
// 合成文件目标规范
libraryTarget: 'umd',
// 配合libraryTarget使用
library: 'libraryName'
}
2-4 webpack 对不同模块规范的支持
1 CommonJS
导入:(同步加载依赖的模块)
var $ = require('jquery')
var myModule = require('my-module')
导出:
module.exports = function addTwo(a,b) { return a+b}
module.exports = function addThress(a,b,c) { return a+b+c}
动态加载(异步加载),require.ensure,接收4个参数,第一个是依赖的异步模块(数组),第二个是异步加载成功后执行的方法,第三个是异步加载失败时执行的方法,第四个是打包后的文件名
require.ensure(
['./add'],
function callback(reuqire){
var add = require('./add');
var a = add(1,2);
var b = sub(3,2);
document.getElementById('show').innerText = '总和为:' + a + b
},
function errCallback(error) {
},
'chunk名称'
)
2 AMD
define 通过方法导出
define(
['模块名称'],
['依赖模块'],
function factoryMethod(
依赖模块的导出结果或者 require,exports,module
){
依赖模块加载完成后调用此方法
}
)
define({
answer: 42
})
require( // AMD异步加载
[依赖的模块列表, './add', './sub'],
function(){
依赖模块异步加载完成,会执行此函数
}
)
3 ES6模块(推荐)
静态导入:
import MyMoudle from './my-module.js'
import { NamedExport } form './other-module.js'
导出:
export function Add(a,b) {
return a+b
}
export default {}
动态加载:
import('loadsh').then(_ => {
// 调用loadsh的方法
})
通过注释来设置chunk名称和加载模式(懒加载)
import(
/*webpackChunkName: 'lodash_chunk'*/,
/*webpackMode: 'lazy'*/,
'loadsh'
).then(_ => {
// 调用loadsh的方法
})