第十三周
Module 模块
初识
- 什么是模块,模块系统
- 防止不同作用域变量相互污染,一个一个的局部作用域的代码块
- 以前:IIFE,缺点:引入顺序需要注意,还是会有全局变量
- 模块系统解决的问题:
- 模块化代码
- 消除全局变量
- 管理加载顺序
- 第三方库:RequireJS seaJS
- 官方原生:ES Module
- 模块内部默认是严格模式
基本用法
-
注意:
- 模块必须在服务器环境才能生效,本地环境不行
- 用live server 就行了
- 后面ajax 也需要服务器的环境
- 打开文件,需要目录的环境才可以使用 live server
-
基本用法
-
// 导入 import Slider from './slider.js'; // 导出 export default BaseSlider; // 引入 <script src='./index.js' type='module'><script>
-
只要加上 type='module' 就把文件变成了模块
-
两种导入导出
-
导入导出
- 一个模块没有导出,也可以将其导入,被导入的代码只会执行一遍,即使导入多次
-
export default —— import
- import 时可以随便起名字,注意语义
- 一个模块只能有一个 export default
- 基本所有数据结构都可以导出,包括简单数据类型
-
export —— import
-
基本用法
-
只能导出声明或语句
-
导入时不能随意命名
-
// 1 export const age = 18; // 2 export { age }; import { age } from 'index.js';
-
-
多个导出
- 和上面第二种方式一样,写到对象里
-
导入导出时起别名
-
export { fn as func, className, age}; import { func, age, className as Person } from 'index.js';
-
-
整体导入
-
export { fn as func, className, age}; import * as obj from 'index.js'; console,log(obj.func)
-
注意!
- export 和 export default 可以一起用,后面这个注意只有一个就行了
- export default 导出的东西在 obj.default 上
-
-
同时导入
-
// 可以单独导入 default ,也可以放在一条语句上,注意不能同名,default 则可以随意取别名 import { func, age, className } from 'index.js'; import age2 from 'index.js'; import age2, { func, age, className } from 'index.js'; // 写在一条语句上时,必须先写 default 的导入
-
-
注意事项
-
模块顶层的this 指向
-
undefined 由此也可以看出不是全局作用域了
-
注意: 导入和引入是一样的,同样的效果,module 中引入了也是模块
-
if(typeof this !== 'undefined'){ throw new Error('请使用模块的方式加载'); }
-
-
import 和 import()
-
import 具有提升效果,会提升到整个模块的头部,率先执行
-
import 只能放在模块的顶层,不能放在代码中执行
-
// 注意!!这里是错误的 if(PC){ import 'pc.js'; }else if(Mobile){ import 'mobile.js'; }
-
import() 就是用来解决这个问题的,返回 Promise 对象
-
if(PC){ import('pc.js').then().catch(); }else if(Mobile){ import('mobile.js'); }
-
import() 只是一个提案,可能会有兼容性问题,但是和后面webpack 一起用就没事了
-
-
导入导出复合写法
-
export { age } from './module.js'; // 等价于 import { age } from './module.js'; export { age } from './module.js';
-
相当于一个中转站,但是这种写法的内容,无法在当前模块使用,并不推荐
-
Babel
Babel是什么
- https://www.babeljs.cn/
- Babel 是JavaScript 的编辑器,用来将ES6 代码,转换成ES6 之前的代码
- Babel 本身是不会转换ES6 的api 的,需要借助其他模块实现,一些关键字语法可以直接实现转换,api 需要再引入其他实现模块,这些模块是由ES6 之前版本语法实现的,对于模块的实现,Babel 也无能为力,需要借助Webpack 实现
Babel使用方式
-
使用前准备工作
-
什么是Node.js 和 npm
- Node.js 是个平台或者工具,对应浏览器
- 后端JavaScript = ECMAScript + IO + File + ...等服务器的操作
- npm:node 包管理工具
-
安装Node.js
-
初始化项目
- npm init
- 生成一个package.json ,这个文件的作用就是记录项目安装了哪些包
- node_modules 文件夹是安装的包的目录
- 使用package.json :npm install,会自动安装package 里面记录的包
-
安装Babel 需要的包
-
npm install --save-dev @babel/core @babel/cli
-
具体命令看官网,这里的 --save-dev 表示开发依赖,上线就看不到了
-
指定版本安装:
-
npm install --save-dev @babel/[email protected] @babel/[email protected]
-
-
-
使用
-
看文档的过程解释:
-
官网这里,表示添加的代码,在package 相应地方添加就可以了
-
前面是命令名,后面是执行的命令,src 是输入路径,也就是源路径,lib 是输出路径,名字都是可以改的
-
-d 是缩写命令, 全称: --out-dir
-
npm run build
-
但是这里直接run 出来的文件和源文件是完全一样的,因为没有配置Babel,接下来设置配置文件
-
Create .babelrc configuration file
-
先安装包:
-
npm install @babel/[email protected] --save-dev
-
至此三个包:
-
@babel/preset-env : 具体改怎么转换ES6 相关语法,预设环境配置
-
@babel/core : 核心包,发布命令,具体还是其他包执行
-
@babel/cli : 使用命令行工具需要的包
-
分多个包就是模块化开发的典型例子
-
有了@babel/preset-env 这个包,再在目录下新建 .babelrc 配置文件
-
{ "presets": ["@babel/preset-env"] }
-
至此就是Babel 能够达到的最好的效果了,api 语法的转化以及模块的处理,后面和webpack 联手解决
-
Webpack
Webpack 是什么
-
认识
- 静态模块打包器
- 动态的东西没办法处理
-
初体验
-
初始化项目
- npm init
-
安装Webpack 需要的包
-
npm install --save-dev [email protected] [email protected]
-
-
配置Webpack
-
webpack.config.js 官网demo:
-
const path = require('path'); module.exports = { // mode: 'development', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', }, };
-
配置这里的源文件
-
-
打包并测试
-
在package.json 中添加命令
-
"webpack": "webpack --config webpack.config.js"
-
不写 --config 默认也是这个文件
-
npm run webpack
-
-
核心概念
entry、output、loader、plugins
-
entry、output
-
单/多 入口文件,单/多 出口文件
-
const path = require('path'); module.exports = { mode: 'development', // entry: './src/index.js', entry: { main: './src/index.js', search: './src/search.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js', }, };
-
[name].js 根据源文件名字
-
-
loader
-
官网:https://www.webpackjs.com/loaders/,这里是官方的,还有很多第三方loader 没有收录
-
webpack 本身是处理js 的,想要处理css /图片 等非js 文件的模块,就需要各种各样的loader ,有官方的有第三方的,非常多,当然了,一些 loader 也是可以处理js 文件的
-
webpack 更像只是一个打包的工具,而其他的功能,比如说编译,就要用到loader 了
-
接下来用babel-loader 举例子学习
-
首先,Babel 是Babel,webpack 是webpack;Babel-loader 可以使它们连接起来,可以通过Babel-loader 使用Babel 的编译功能,然后再由webpack 把编译好的东西打包好,而真正编译的不是Babel-loader 而是Babel
-
安装包:
-
npm install --save-dev [email protected] @babel/[email protected] @babel/[email protected]
-
再在目录下新建 .babelrc 配置文件
-
{ "presets": ["@babel/preset-env"] }
-
修改 webpack.config.js 文件,添加loader
-
const path = require('path'); module.exports = { mode: 'development', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js', }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' } ] } };
-
但是这时还是那个问题,只转换了关键字语法,没转换 api 的语法,我们需要一个“ 垫片 ”解决这个问题:core-js
-
安装包:(Babel 官网查看其他详情)
-
npm install --save-dev [email protected]
-
在需要转换的文件中添加:
-
import 'core-js/stable'
-
-
-
plugins
-
loader 被用于帮助webpack 处理各种模块,而插件则可以用于执行范围更广的任务
-
本节课选择HtmlWebpackPlugin 展开学习
-
作用:把loader 处理完的代码嵌入到html 中,并生成新的文件到项目目录中
-
安装包:
-
npm install --save-dev [email protected]
-
配置webpack.config.js
-
单文件:
-
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: 'development', entry: { index:'./src/index.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js', }, plugins:[ new HtmlWebpackPlugin({ template: './index.html' }) ] };
-
多文件:
-
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: 'development', entry: { index:'./src/index.js', search:'./src/search.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js', }, plugins:[ new HtmlWebpackPlugin({ template: './index.html', filename: 'index.html', chunks: ['index'] }), new HtmlWebpackPlugin({ template: './search.html', filename: 'search.html', chunks: ['search'] }) ] };
-
chunks 不添加,会把所有产出的js 文件都添加上
-
HtmlWebpackPlugin 还有其他功能,详细见文档
-
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // mode: 'production', mode: 'development', entry: { index:'./src/index.js', search:'./src/search.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js', }, plugins:[ new HtmlWebpackPlugin({ template: './index.html', filename: 'index.html', chunks: ['index'], minify: { // 删除注释 removeComments: true, // 删除空格 collapseWhitespace: true, // 删除标签属性值的双引号 removeAttributeQuotes: true } }), new HtmlWebpackPlugin({ template: './search.html', filename: 'search.html', chunks: ['search'] }) ] };
使用webpack 处理其他模块
-
处理css 文件
-
loader 让webpack 可以在js 中引入css,认识css 文件
-
// js 中引入css 直接import import './index.css'; // 安装css-loader npm install --save-dev [email protected]
-
这里loader 还不够,现在只是认识了css 文件,不会报错,但还没有生效,它不知道要以style 的方式还是link 的方式引入到html 中,如果是style 方式,则需要其他loader ,如果是link 方式,需要其他plugin ,然后再使用这个插件里的loader ,大概是这个意思,插件功能大于loader
-
// style loader: npm install --save-dev [email protected] // 多个loader 作用: // 注意是从右到左生效 module: { rules: [ { test: /\.css$/, // loader: 'css-loader', use: ['style-loader', 'css-loader'] } ] }
-
// link 需要的plugin // 安装: npm install --save-dev [email protected] // 配置: const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { ... module: { rules: [ { test: /\.css$/, // loader: 'css-loader', // use: ['style-loader', 'css-loader'], use: [MiniCssExtractPlugin.loader, 'css-loader'] } ] }, plugins = [ new MiniCssExtractPlugin({ filename: 'css/[name].css' }) ] }
-
-
处理css 文件中的图片 file-loader
-
如果是外部资源,是不需要考虑webpack 的,只有本地的资源才需要被webpack 处理
-
就像不认识 .css 一样,也不认识 .png 因此需要一个合适的loader
-
// 安装 file-loader npm install --save-dev [email protected] // 配置 rules: [ { test: /\.(jpg|png|gif)$/, use: 'file-loader' // 这里 use 和 loader 都行 } ]
-
复制资源到dist 目录下,并且改变了源码中资源的路径,但是目前这里路径改变的有问题,我们在设置css plugin 的时候,设置的路径是 'css/[name].css' 这里并不是dist 主路径,而资源打包默认放在 dist 路径下面,而不是css 路径下面,因此使用 css plugin 时添加一些参数:
-
rules: [ { test: /\.css$/, use: [{ loader: MiniCssExtractPlugin.loader, options: { publicPath: '../' } }, 'css-loader'] } ]
-
// 自定义资源路径: rules: [ { test: /\.(jpg|png|gif)$/, use: { loader: 'file-loader', options: { name: 'img/[name].[ext]' // 这里name 就是资源本身的名字不是前面entry 名字,ext 就是原后缀 } } } ]
-
-
处理html 中的图片 html-withimg-loader
-
css 中的图片在 entry 的js 中可以找到,但是html 只是作为模板加载,因此里面的内容其实也是默认不处理的,图片不会被复制到dist ,也不会正常显示
-
// 安装 npm install --save-dev [email protected] // 配置 rules: [ { test: /\.(htm|html)$/, loader: 'html-withimg-loader' } ] // 这一步的结果有问题: <img src={"default": "img/logo.png"} alt="" /> // 这里的结果和file-loader 相关,这两个loader 是一起干活的,其实还是file-loader 解析的,file-loader 默认就是ES6 模块的方式导出的,export default // 解决办法: // options 中 添加属性 esModule: false rules: [ { test: /\.(jpg|png|gif)$/, use: { loader: 'file-loader', options: { name: 'img/[name].[ext]', esModule: false } } } ]
-
-
处理js 中的图片 file-loader
-
js 中的图片也可以和css 一样引入,但是这里需要有个名字,方便后面使用
-
import img from './img/logo.png' console.log(img) // file-loader 先把图片复制到dist 目录中,再修改img 的指向
-
-
使用 url-loader 处理图片
-
实际项目中,我们可能会把一些小图片用编码的形式嵌入到html 或者css 中,这些图片编码已经变成了html 和css 文件的一部分,这样网页就不需要多次请求了,file-loader 的功能单一,无法处理,有了url-loader 就不需要配置file-loader 了,但是url-loader 底层还是用到了file-loader ,都需要安装
-
// 安装 npm install --save-dev [email protected] // 配置 rules: [ { test: /\.(jpg|png|gif)$/, use: { loader: 'url-loader', options: { name: 'img/[name].[ext]', esModule: false, limit: 10000 // 小于10K的,转成64 位格式的,大于的还是使用file-loader } } } ]
-
上面这一堆,就是图片base64 编码,把它放到src 上就可以使用,图片越大,转成的编码占的空间也大,js 文件也会越大,转成编码格式,就不会复制图片到dist 了
-
搭建开发环境
webpack-dev-server:保存自动打包,不会生成dist 目录,在内存中,会打开默认浏览器
npm install --save-dev [email protected]
// 命令
'script': {
"webpack": "webpack",
"dev": "webpack-dev-server --open chrome"
}
标签:index,13,Babel,webpack,js,Webpack,import,loader,css
From: https://www.cnblogs.com/autowe/p/17180007.html