模块化开发
为什么用模块化开发?
原因:1.主要是js文件依赖于导入顺序几乎是强制性的,当导入的多个js文件使用相同的变量名时,就会出现下层变量名覆盖上层变量名情况。
解决1:使用闭包函数,形成局部作用域。
(function(){
var flag = true
})()
问题2:当使用闭包函数时,文件之间变量就不能被引用
解决2:在闭包函数内定义一个对象,并把它返回。
var moduleA = (function () {
var obj = {};
var flag = true;
obj.flag = flag;
return obj
})()
这样,在其它文件下直接通过 modelA.flag 拿到变量,但是现在模块化已经有成熟的模板。
已存在的模板规范:
CommonJS, AMD, CMD, ES6的Modules,
模板化的核心:导入和导出,如:
CommonJS导入
module.exports = {
flag: ture,
test(a, b) {
return a + b
},
demo(a, b){
return a * b
}
}
CommonJS的导入
let {test, demo, flag} = require("modelA")
// 等同于
let mA = require('moduleA');
let test = mA.test;
let demo = mA.demo;
let flag = mA.flag;
ES6中的模块化
export和import基本使用
在a.js文件代码
var flag = true;
function sum(a, b) {
return a + b
}
export {
flag, sum
}
在b.js文件下导入,全部导入可以使用
import {sum} = from "./a.js";
console.log(sum(2, 3));
其他导出方式
导出变量
export let num = 100;
导出函数/类
export function sum(a, b) {
return a + b
}
// 导出类(ES6语法)
export class Person() {
run () {
return "running...."
}
}
export default
某些情况下,一个模块中包含某个的功能,我们并不希望给这个功能命名,而且让导入者可以自己来命名
export default function () {
return "export default"
}
// 导入使用
import myFunc from "./info.js"
注意: export default在同一模块中,有且只能存在一个。
webpack 使用
从本质上来讲,webpack是一个现代的JavaScript应用的静态模块打包工具。
主要功能:把各种模块化开发的代码,打包成大多数浏览器都能识别的代码。比如处理模块之间的关系;压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作。
webpack安装
官网:https://webpack.js.org
- 先安装node,最好是10版本以上
- 安装npm,修改镜像源
- npm init -y ,初始化npm
npm install -g cnpm --registry=https://registry.npm.taobao.org
- 安装webpack
#全局安装
cnpm install webpack@3.6.0 -g
#局部安装,主要用于package.json中定义了scripts时,包含了webpack命令,那么使用的就是局部webpack'
cnpm install webpack@3.6.0 --save-dev
webpack简单使用
创建以下文件夹
dist文件夹:用于存放之后的打包文件
src文件夹:用于存放我们写的源文件
main.js:项目的入口文件
info.js:可以是各种模块化方式导出
index.html:首页
webpack.config.js配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 打包html插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 单独分离css文件插件
const TerserPlugin = require('terser-webpack-plugin'); // 压缩文件插件
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); // 压缩css插件
let mode = 'development'; // 开发模式
// 配置入口
let entry = { // 要打包的文件路径
index: './src/js/index/index.js',
detail: './src/js/detail/index.js',
search: './src/js/search/index.js',
}
// 配置打包后,出口
let output = {
filename: 'js/[name].js', // 打包后的文件名
path: path.resolve(__dirname, 'dist'), // __dirname:绝对路径以此文件位置;js打包后的位置
}
// 配置插件,打包html
let plugins = [];
let htmlPlugin = new HtmlWebpackPlugin({
template: path.resolve('./src/html/index.html'), // 要打包的html文件位置
// filename: './html/index.html', // 打包后html的名字
filename: 'index.html',
chunks: ['index'] // 打包后html文件引入的js文件名
})
let htmlPlugin1 = new HtmlWebpackPlugin({
template: path.resolve('./src/html/detail.html'), // 要打包的html文件位置
// filename: './html/detail.html', // 打包后html的名字
filename: '/detail.html',
chunks: ['detail'] // 打包后html文件引入的js文件名
})
let htmlPlugin2 = new HtmlWebpackPlugin({
template: path.resolve('./src/html/search.html'), // 要打包的html文件位置
// filename: './html/search.html', // 打包后html的名字
filename: 'search.html',
chunks: ['search'] // 打包后html文件引入的js文件名
})
let miniCss = new MiniCssExtractPlugin({
filename:'css/[name].css', // 打包后css文件存入的路径 和 文件名
});
let terserPlugin = new TerserPlugin(); // 引用插件
let cssMini = new CssMinimizerPlugin(); // 引用插件
plugins.push(htmlPlugin, htmlPlugin1, htmlPlugin2,miniCss,terserPlugin,cssMini); // 把引用的插件添加进 plugins中(只要引用插件都要添加)
// 配置css-loader
let module_ = {
rules: []
}
module_.rules.push(
// 打包css
{
test: /\.css$/, // 正则判断 css文件
use: [
// 'style-loader', // 引入插件
MiniCssExtractPlugin.loader,
'css-loader'
],
},
// 配置打包图片
{
test: /\.(png|jpg|gif)$/i, // 正则 判断图片格式
loader: 'file-loader', // 引入插件
options: {
publicPath: '../', // 解决chunk(代码块)加载静态资源路径问题
name: './imgs/[name].[ext]', // 打包后图片的位置和名字
},
},
// 配置 字体图标
{
test: /\.(eot|ttf|woff|woff2|svg)$/, // 正则判断字体图标的文件类型
loader: 'file-loader', // 使用file模块
options: {
name: '[name].[ext]', // 打包后的文件名
outputPath: 'font', // 打包后存入的路径
}
},
)
// 把mode 入口 出口等加入module.exports对象中
module.exports = {
mode,
entry,
output,
module: module_,
plugins,
// 配置 webpack-dev-server 自动编译 启动浏览器
devServer:{
// 当webpack服务启动时候,运行那个文件中的代码
contentBase: './dist', // 注意:必须是打包后的跟路径 dist
compress: true, // 对打包文件进行压缩
port: 9000, // 设置端口号
open: true, // 启动后自动打开浏览器
}
}
webpack 一些插件和模板
"webpack": "^5.24.4",
"webpack-cli": "^4.5.0"`
"css-loader": "^5.1.2",
"css-minimizer-webpack-plugin": "^1.2.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.1",
"html-withimg-loader": "^0.1.16",
"mini-css-extract-plugin": "^1.3.9",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack-dev-server": "^3.11.2"``
注意事项
css:
css-loader只负责将css文件经行加载,不负责渲染
使用style-loacer负责将样式添加到DOM中
使用多个loader时,加载顺序是从右往左,需要先加载css-loader
img:
当图片大小小于limit时,会将图片编译成base64格式
当图片大小大于limit时,会使用file-loader模式加载,这时会在dist文件内生成一个相同的图片,如果找不到,则需要在output下配置
img/ : 路径,文件要打包到的文件夹
name : 获取图片原来的名字,放到该位置
hash:8 : 为了防止图片冲突,使用hash,但只保留8位
ext : 使用图片原来的扩展名
webpack-dev-server
本地服务器,基于node.js搭建,内部使用express框架,会在内存中生成dist文件,可以让浏览器很快的自动刷新修改后的结果。
需要下载webpack-dev-server模块
npm run 脚本名
用户可以在npm的配置文件中添加自己的脚本内容,然后使用下面给出的指令来运行用户的脚本