随着前端项目复杂程度越来越高,依赖也越来越多,为了提高项目中代码的可复用性,前端开始提出模块化开发的思路,前端模块化会有以下几个痛点:
命名冲突
文件依赖
代码复用
模块化,会将相关的代码封装成一个package包的文件,当需要的时候,直接拿来用即可(import引入)。至于相关文件的直接依赖如何处理,webpack会帮我们解决这个问题。那么模块化应该使用什么样的规范呢?常见的模块化的标准主要如下:
commonjs
nodejs使用的就是commonJs的规范,采用的同步方式加载依赖,一个文件就是一个模块。
导入导出方式如下:
导入:const aa = require(‘./aa‘)
导出:module.exports = aa.fun
缺点是加载的模块是同步的,只有加载完才能执行后面的操作。因为 node.js 的模块文件一般存在于本地硬盘,所以一般不会出现这个问题,但是在浏览器环境该规范就不那么适用了。
AMD
因为commonJS不适用于浏览器的环境,所以出现AMD规范。特点: 异步加载/推崇依赖前置、提前执行 。require.js最佳实践
使用方式:
定义模块: define()
加载模块:require()
引用:require.config()
CMD的使用方式如上,但是特点不太一样。CMD是异步加载/依赖就近、延迟执行 sea.js最佳实践
ES6
ES6 直接在语言层面上实现了模块化。我们现在用的最多的就是 ES6 模块化的实践方式。
导入导出方式如下:
导入:
import aa from ‘aa‘
import {A} from ‘aa‘
导出:
export default {A, B}
export {A, B}
export funtion aa() {}
虽然ES6是模块化的最终方案,但是还是在许多浏览器上有兼容问题,需要对代码进行转码处理才行。
样式文件中的模块化
前端开发中,样式文件也开始支持模块化,以stylus为例,通常将一些通用的文件放到文件中,在使用相关的样式时,直接@import引入文件,就能使用对应的代码片段,当然也能定义一些全局的参数(颜色,圆角类)进行使用。
// common.styl
.center-transform
top 50%
left 50%
transform translate(-50% -50%)
center-transform()
top 50%
left 50%
transform translate(-50% -50%)
// 使用
@import ‘common.styl‘
.box {
center-transform
}
webpack和Gulp/Grunt、Rollup比较
开始使用webpack
首先创建一下的目录结构:
.
├── src
│ ├── assemble
│ │ ├── css
│ │ │ ├── index.css
│ │ ├── index.html
│ │ └── js
│ │ ├── index.js
│ │ └── test.js
│ ├── babyTest
│ │ ├── css
│ │ │ └── index.css
│ │ ├── index.html
│ │ └── js
│ │ └── index.js
文件内容:
// 1. assemble-index.html:
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>
// 2. assemble-css/index.css:
body {background: red}
// 3. assemble-js/index.js:
import ‘../css/index.css‘
console.log(‘index.js‘)
// 4. assemble-js/test.js:
console.log(‘test.js‘)
babyTest目录和上面类似
创建webpack.config.js文件,下面直接配置的是多文件入口:
// 引入插件
const HtmlWebpackPlugin = require(‘html-webpack-plugin‘)
// 相关配置
module.exports = {
mode: ‘development‘, // 指定webpack的模式
entry: {
‘assemble/js/index‘: ‘./src/assemble/js/index.js‘,
‘assemble/js/test‘: ‘./src/assemble/js/test.js‘,
‘babyTest/js/index‘: ‘./src/babyTest/js/index.js‘
},
output: {
filename: ‘[name].js‘, // 打包后输出文件的文件名
path: path.resolve(‘./output/market‘) // 打包后的文件存放的地方
},
module: {
rules: [
{
test: /\.css$/,
use: [‘style-loader‘, ‘css-loader‘]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: ‘./src/assemble/index.html‘,
filename: ‘assemble/index.html‘,
chunks: [‘assemble/js/index‘]
}),
new HtmlWebpackPlugin({
template: ‘./src/babyTest/index.html‘,
filename: ‘babyTest/index.html‘,
hash: true,
chunks: [‘babyTest/js/index‘]
})
]
}
上面写的实例中,将loader和plugins已经使用了,可以先按照上面的使用,后边将进行详细方法的介绍。
使用前,安装对应的依赖包
npm install css-loader style-loader html-webpack-plugin -D
可以看到在根目录下有output目录,里面就行对应的打包文件。直接运行output文件下的目录,能够看到对应效果,css和js都能够执行成功。
备注:执行打包命令的方式有以下几种方式
node_modules/.bin/webpackwebpack在package.json文件中配置对应的命令 "scripts": { "start": "webpack"}
entry
入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
每个依赖项随即被处理,最后输出到称之为 bundles 的文件中,,entry属性 来指定一个入口起点(或多个入口起点)。默认值为 ./src。
output
output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。
Loader
loader 用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!
上面的配置中就用到了 css-loader和style-loader,主要是在对引用的css文件会用style-loader和css-loader进行处理,当配置多个loader的时候,按照从左至右的方式进行处理。
Loaders的配置主要包含以下配置:
在webpack中使用的方式
联系紧密的Babel
Babel是一个编译JavaScript的平台,可以帮我们将编译的代码
Babel的安装与使用
Babel其实是几个模块化的包,其核心功能称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用的最多的就是解析ES6语法的包 babel-preset-env)
npm install --save-dev babel-core babel-loader babel-preset-env
在webpack.config.js中,module的rules中添加;
{
test: /\.js$/,
use: {
loader: ‘babel-loader‘,
options: {
presets: [
‘env‘, ‘react‘
]
}
},
include: /src/,
exclude: /node_modules/
}
Babel的配置可以直接在webpack.config.js中进行配置,但是有时配置项过多,但在这个文件中配置过多js编译规则的代码,显得可读性不太好,因此支持在.babelrc中单独配置,webpack会自动调用这个文件中的配置项。
// .babelrc文件
{
"presets": ["react", "env"]
}
loader的特性(引用官网)
扩展-常使用的loader清单
loader name | 介绍 |
---|---|
css-loader | 解析@import 和 Url()引用的css文件,转化成 import/require() 的方式然后在解析他们 |
style-loader | 将 CSS 放在 <style></style> 标签中注入到 DOM 中 |
sass-loader | 将 SASS/SCSS 转换为 css |
less-loader | 将 less 转化为 css |
html-loader | 将 html 输出为字符串,也可以根据配置进行压缩 |
babel-loader | 加载 ES2015+ 代码,然后使用 Babel 转译为 ES5 |
url-loader | 将文件加载为 Base64 编码的 URL |
file-loader | 可以解析项目中的url引入(不仅限于css),根据我们的配置 |
plugin
插件是 webpack 的支柱功能。webpack 自身也是构建于,你在 webpack 配置中用到的相同的插件系统之上!插件目的在于解决 loader 无法实现的其他事。
Plugins在构建的过程中,通过在构建流程中注入对应的钩子,给webpack带来很大的灵活性。
Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,Plugins并不直接操作单个文件,它直接对整个构建过程其作用
上面的实例中就使用了html-webpack-plugin插件,主要的功能就是自动引用使用的js文件,使用css的话,也会根据一定规则进行动态插入,在控制台查看文件代码时,可以看到引用的css文件,会自动插在<head></head>之间。如截图所示
我们可以根据自己的项目构建方式,使用对应的插件,就不一一举例说明了。
扩展-常用的Plugins清单
Plugins name | 介绍 |
---|---|
HtmlWebpackPlugin | 简单创建 HTML 文件,用于服务器访问 |
clean-webpack-plugin | 删除指定的文件夹 |
webpack-bundle-analyzer | webpack打包体积查看,便于优化文件体积 |
speed-measure-webpack-plugin | 查看测量出在你的构建过程中,每一个 Loader 和 Plugin 的执行时长(优化webpack时能帮你看出对应的时间) |
启动静态服务器
启动一个静态服务器,默认会自动刷新,就是说你对html,css,js文件做了修改并保存后,浏览器会默认刷新一次展现修改后的效果
正常情况下我们都是在开发环境中开发项目,所以之前配置的脚本"dev"可以派上用场了,在执行npm run dev命令后,会启动静态服务器,我们访问localhost:3000端口就可以看到开发的页面内容了
对应的配置文件:
// webpack.config.js的配置文件
devServer: {
host: ‘localhost‘, // 默认是localhost
port: ‘3000‘, // 端口
open: true, // 自动打开
hot: true, // 开启热更新
openPage: ‘assemble‘ // 默认打开的文件
}
// package.json中的配置
"scripts": {
"dev": "webpack-dev-server --open"
}
开发、测试、上线构建的细微区别
通常本地开发,测试和线上的构建方式略微有点区别,线上文件都会将文件中的空行,空格,换行清除,并且压缩html,css,js和对应image的体积,这样就能保证体积最小,加快页面的加载速度。
但是开发和测试环境通常,在浏览器中,无法对代码逐行打断点进行调试,所有需要使用source maps进行调试,它使得我们在浏览器中可以看到源代码,进而逐行打断点调试。
使用source maps方法
在webpack.config.js文件中,添加devtool属性,赋值为 source-map或者inline-source-map即可,后者报错信息更加具体,会指示源代码中的具体错误位置,而source-map选项无法指示到源代码中的具体位置。
广州品牌设计公司https://www.houdianzi.com PPT模板下载大全https://redbox.wode007.com
webpack优化
1. 代码编写过程中遇到的现象
问题描述:更改一个文件,导致所有的文件都会重新进行编译。
优化方案:使用缓存