提到前端的模块化,很多朋友第一时间想到的就是 AMD ,CMD, CommonJS 以及 ES Modules这些。
不过,这些都是js文件的模块化,而一个前端项目并不是只有js文件。
一个前端项目中,除了js文件 还有html,css,图片字体等等各种文件,既然是前端模块化,那么所有的前端资源都需要模块化。
总结一下我们前端项目模块化,需要支持以下几个功能:
前端的模块化打包工具,常见的有 webpack , rollup , parcel
webpack
它的核心特性就能很好的满足上面我们的需求,它为处理资源管理和分割代码而生,可以包含任何类型的文件。灵活,插件多。
rollup
用标准化的格式(es6)来写代码,通过减少死代码尽可能地缩小包体积。
parcel
超快的打包速度,多线程在多核上并发编译,不用任何配置。
打包工具解决的是前端整体的模块化,并不单指 JavaScript 模块化
webpack 依赖node环境运行,首先保证已经安装了node
然后在项目中安装对应的包 webpack 和 webpack-cli
安装包可以使用npm 或者 yarn
具体区别体现在运行上:
默认的约定
直接执行webpack 会默认把当前项目中 src 目录下的 index.js 打包到 dist 目录下 生成 main.js
并且webpack 默认自带处理ES Moudules语法的功能
上面我们说到,默认的打包目录。这个目录是可以通过项目根目录中的 webpack.config.js 这个文件进行修改的。
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.join( __dirname )
}
}
在我们执行webpack打包命令的时候 会发现有一行警告提示:
WARNING in configuration
The ‘mode’ option has not been set, webpack will fallback to ‘production’ for this value.
Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for each environment.
意思就是说,让我们去设置打包的模式。webpack的打包模式有三种:
设置打包模式可以通过两种方式:
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist/')
}
}
如果要想让webpack处理资源模块的打包,那么各种文件对应的loader就必不可少,Loader是webpack的核心特性。
借助于Loader就可以加载任何类型的资源。
加载器大致可以分成三类:
如果我们现在为项目中添加了css文件,也想通过webpack进行打包
那么此时运行webpack打包就会出现报错
ERROR in ./src/style/index.css 1:5
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
这是报错中的 You may need an appropriate loader to handle this file type
这句 意思就是说 你可能需要一个loader来处理这种类型的文件。
比如上面的 css 文件 我们可以借助于 style-loader 和 css-loader 其中 style-loader的作用是把样式添加到dom中, css-loader是用于把css打包到bundle.js中 ( 其实就是读取样式文件内容 转化字符串记录在数组或者对象中 )
module.exports = {
mode: 'none',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist/')
},
module: {
rules: [
{
test: /.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}
在webpack.config.js 中添加module属性 在rules数组里,每一个成员对应了一种需要通过loader处理的文件类型。
test用于匹配对应后缀名的文件, use 表示要使用的loader 这里loader的使用顺序是不能乱写的 要遵循从后往前调用的原则。
webpack不仅仅是可以让我们在js中引入css代码,它建议我们引入任何类型,我们当前代码需要的资源文件
真正需要这些资源的不是应用,而是我们当前编写的代码。
如果是一些图片资源在js中导入,webpack的处理原理如下:
其实就是把对应文件复制到了打包结果目录中,同时把该文件的路径导入到了bundle.js中。
我们使用的Loader是 file-loader, 打包后的图片文件会默认以网站根目录的路径进行导入,如果需要指定文件夹需要在output中配置publicpath
import icon from './assets/icon.png'
let img = new Image()
img.src = icon
document.body.append(img)
module.exports = {
mode: 'none',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist/'),
publicPath: 'dist/'
},
module: {
rules: [
{
test: /.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /.png$/,
use: ['file-loader']
}
]
}
}
这里的url 加载器 指的就是 url-loader, 这个loader的作用可以把资源文件转化为Data URL。 一旦文件转为data url之后 dist目录中就不会复制文件了。
我们可以通过一些参数来设置一个值,让超过这个值大小的文件 依然以file-loader处理 ,小于这个值的文件转为data url
要想使用 url-loader 我们需要先安装file-loader
module.exports = {
mode: 'none',
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
publicPath: 'dist/'
},
module: {
rules: [
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /.png$/,
use: {
loader: 'url-loader',
options: {
limit: 10 * 1024 // 10 KB 超过10kb的就还是用file-loader 复制文件 引入路径
}
}
}
]
}
}
webpack 默认只能处理模块化的语法,因为它本身就是为了实现模块打包的,但是它并不支持所有的新特性,所以我们需要借助于babel-loader 来处理js代码中的新特性
需要安装 三个包
"@babel/core","@babel/preset-env", "babel-loader"
{
test: /.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
处理html文件中的src属性 或者 a 标签的href属性 ,需要借助于 html-loader
{
test: /.html$/,
use: {
loader: 'html-loader',
options: {
attrs: ['img:src', 'a:href'] // 表示要处理的src 和 href
}
}
}
Loader 负责资源文件从输入到输出的转换,webpack要求输出的必须要是js的代码,我们可以对于同一个资源依次使用多个 Loader 处理
loader代码
const marked = require('marked')
// source 接收所有的匹配到的资源内容
module.exports = source => {
return marked(source)
}
webpack.config.js 代码
{
test: /.md$/,
use: [
'html-loader',
'./src/loader/md_loader.js'
]
}
导入md的代码
import './style/index.css'
import noteStr from './note.md'
const noteDiv = document.createElement('div')
noteDiv.innerHTML = noteStr
document.body.append(noteDiv)
如果你想对使用手机,平板电脑和辅助技术的用户隐藏某些内容,而只对键盘用户显...
本文分享自华为云社区《 架构可视化支撑系统演进探索 》原文作者无名小溪。 随着...
最近在和团队规划OKR目标的时候,我们讨论了很多问题,我先抛砖引玉,列举了一些...
一. RabbitMQ 简介 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用...
ajax传送json格式数据,关键是指定contentType,data要是json格式 如果是restful...
一、导读 本文主要介绍Redhat7.6系统安装oracle 12201版本RAC的一些坑以及避坑方...
Afrikaans:af Albanian:sq Basque:eu Belarusian:be Bulgarian:bg Catalan:ca Ch...
今天给大家分享四个在实际开发中,比较实用的SQL Server脚本函数,希望对大家能...
Linux 发行版的爱好者们又有全新的 Linux 可以体验了,日前一款名为 TeLOS 的 Li...
Eval 计算一个表达式的值并返回结果。 语法:[result = ]eval_r(expression_r) e...