序言
如今,大多数项目打包都是用webpack打包的。可能会有某种诱因,例如带宽,节省服务器资源等,以及访问性能,这将需要我们按需打包,打包的文件尽可能小,并与一些较低版本的浏览器兼容。
那么如何按需引入,以及如何按需打包呢?我们明天上去详细阐述一下!
让我们回到正题
之后webpack css按需加载,我们将做一些测试来逐步解释如何按需引用和打包。
我们先写一个 ES6 句型的测试代码,如下:
src/index.js 文件
const fn = ()=>{
console.log('this is fn()')
}
fn();
new Promise(()=>{})
Array.from(new Set([1,2,3,4]))
class A { }
运行 npmrunserve 命令,启动后单击 F12 并选择 源 选项以查看我们的打包文件,如下所示:
图片.png
可见,我们写的ES6句型,不是换成了ES5句型吗?
可能会有朋友说,通天塔还没介绍呢!
它没有引入,那么它为什么要引入通天塔,通天塔又偷偷做了什么?
说到通天塔,
不得不提 preset 包 @babel/preset-env,说明 babel 本身无法将 ES6 转换为 ES5,它只是提供了一个依赖 babelcore 的平台。这就是Babelcore所做的吗?答案是否定的,它只是相当于一个组织者,组织各种句型对应的插件。
简单地说:预设包是许多 babel 插件的集合,用于解析多个 ES6 句型。
但预置包不是灵丹妙药webpack css按需加载,它只能转换浏览器不兼容的句子,如 const、let、class 和箭头函数等,而不能转换新的 API,如 Peomise、Set、Map 和 Object.assign()。
怎么办?此时,另一个包@babel/polyfill,也称为服务包。它包含两个插件
core-js:实现除 asyncawait 之外的所有 ES6、ES7 和 ES8 句型
再生运行时:实现异步等待
让我们去掉最关键的异步,配置 babel
安装 babel 相关软件包
npm install -D babel-loader @babel/core @babel/preset-env
在 webpack.config .js文件中配置规则
module:{
rules:[
// 处理 ES6 => ES5
{
test: /.js/, // 需要处理的文件类型
include: [resolve('src')], // 需要梳理的文件
// 组合一 use 后面跟字符串
use: 'babel-loader',
// 组合二 use 后面是数组,每项元素是对象,可单独配置 或者 数组每项是字符串,相当于组合一
// use: [
// {
// laoder: 'babel-loader',
// options: {
// presets: [],
// plugins: []
// },
// }
// ],
// use: ['babel-loader'],
// 组合三 loader + options
// loader: 'babel-loader',
// options: {
// presets: [],
// plugins: []
// }
}
]
}
创建一个 babel.config .js文件并对其进行配置
module.exports = function(api) {
api.cache(true); // 缓存加快打包
// 每个预设 都是一个数组,包含 第一项是名称,第二项是配置
// const presets = [
// [
// '@babel/preset-env',
// {
// // 如需要配置项
// }
// ],
// [
// // 其他配置项
// ]
// ]
// 如果不需要配置,可简写
const presets = ['@babel/preset-env'];
const plugins = [];
return {
presets, plugins
}
}
再次运行 npmrunserve 命令,启动后单击 F12 并选择 源 选项以查看我们的打包文件,如下所示:
图片.png
从上面可以看出,ES6句型早已转化为ES5句型。
但是有一个问题还没有解决:生成的文件包含一个承诺,这意味着旧的浏览器不支持它,这可能会导致我们的项目无法正常工作。
这是我们讨论过的包@babel/polyfill。
安装
npm install @babel/polyfill -D
在程序头部引入
import '@babel/polyfill’
配置完成后,npmrunserve 命令,启动后单击 F12,选择 源 选项查看我们的打包文件,并且已经添加了 Promise 和相关定义。
问题又来了,文件大小
引入 @babel/polyfill 后的 package 变大,也就是说,不管你现在的浏览器是否支持 Promises,都会被重新定义,造成资源浪费。
我们想要的是结果:
如果浏览器不支持我们引入@babel/polyfill,否则不会引入。
要解决这个问题,你只需要在 babel.config .js中配置 useBuiltlns,有三种解决方案不需要在程序文件中单独介绍,如下所示:
配置为 useBuiltlns:false
const presets = [
[ '@babel/preset-env' ]
]
等同于
const presets = [
[
'@babel/preset-env',
{
"useBuiltlns": "false"
}
]
]
特征:
配置为 useBuiltlns:entry
const presets = [
[
'@babel/preset-env',
{
"useBuiltlns": "entry", // 默认是 false 即全部打包
"corejs": 2,
"targets": { //指定浏览器兼容的最低版本
"edge": 70,
// "ie": 10,
"chrome": 67
}
}
]
]
特征:
配置为使用构建lns:usage
const presets = [
[
'@babel/preset-env',
{
"useBuiltlns": "usage", // 默认是 false 即全部打包
"corejs": 2,
"targets": { //指定浏览器兼容的最低版本
"edge": 70,
// "ie": 10,
"chrome": 67
}
}
]
]
特征:
至此,文档的研究结束,项目文件按需导入打包。
赶紧试试吧,记得点赞转发哦~~~
开始之前,我们先看一下下面几张Webpack官网首页的图片,思考一下官网的图片给我们传达的意义
1. Webpack基本介绍 1.1 概念介绍
思考:在网页中,我们经常引入哪些常见的静态资源
CSSImages字体文件(Fonts)模板文件
问题:网页静态资源过多后存在的问题
由于重复发送资源请求来处理复杂的依赖关系,导致网页加载速度变慢
如何解决以上两个问题呢?
可以使用之前学习的requireJS进行图片的合并、压缩、精灵、Base64编码webpack引入js,也可以使用webpack解决包之间复杂的依赖关系; 1.2 什么是Webpack?
webpack是后端项目构建工具,是基于node.js开发的后端工具
上述两种方案如何实现呢?
使用Gulp是基于task任务的; 使用Webpack是基于整个项目的; 1.3 Webpack支持的规范
Webpack 支持以下规范
CommonJS 规范
//moduleA.js 导出
module.exports = function(){
//...
}
//moduleB.js 导入
var moduleA = require('./moduleA')
AMD规范(仰慕靠后定位)
//moduleA.js 导入和导出
define(['jquery','./math.js'],function($,math){
//AMD是依赖前置,将文件的依赖通过数组的形式导入,然后当作函数的参数传递进函数使用
//通过return来实现对外接口
return helloWorld
})
CMD规范(尊重附近的依赖关系,需要时加载模块)
标准句型:define(id?,deps?,factory)
define(fcuntion(require,exports,module){
var $ = require('jquery.js')
})
ES6规范
//moduleA.js 导出
//...内容区
//导出函数(还可以导出对象以及任何你想导出的数据类型)
exports.func = someFunc
//moduleB.js 导入
import func from './moduleA'
雄鹿:AMD和CMD的区别
1.4 安装Webpack 运行 npmiwebpack -g 全局安装Webpack,这样就可以全局使用Webpack命令,并在项目根目录下运行 npmiwebpack --save-dev 安装到项目依赖中 1.5 命令行的使用
npm info webpack
npm install webpack@版本号
npm uninstall webpack webpack-cli -g
2. Webpack 的基本使用 2.1 Webpack 的基本使用 - 示例
目标:使用Webpack构建交错变色案例列表
创建基本目录结构
webpack 研究
运行npminit初始化项目目录下的项目
使用 npmijquery --save 安装 jquery 解释器
创建main.js并编写改变每行颜色的代码逻辑
main.js
//导入jquery内库
import $ from 'jquery'
$(function(){
$("li:odd").css('backgroundColor','red')
$("li:even").css('backgroundColor','tomato')
})
页面中直接引用main.js会报错,因为浏览器无法识别ES6新句型导入,所以需要使用Webpack进行处理。 默认情况下,Webpack 会将这些中间句型转换为低级浏览器可以识别的句型。
运行webpack入口文件路径输出文件路径处理main.js
webpack ./src/main.js ./dist/bundle.js
引入bundle.js来替换index.html中的main.js
2.2 Webpack基本配置
问题描述:
期望达到:
实现方法
const path = require('path')
module.exports = {
entry:path.join(__dirname,'./src/main.js'),
output:{
path:path.join(__dirname,'./dist'),
filename:'bundle.js'
}
}
3.使用webpack-dev-server 3.1实现手动打包编译
问题描述:每次改动代码,都需要自动执行webpack命令打包编译文件,比较冗长
目标:每次修改代码后点击保存后可以帮我们手动打包编译
安装 webpack-dev-server
npm install webpack-dev-server -D
将 webpack-dev-server 命令添加到package.json 上的scripts 属性上方的开发环境中
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"dev": "webpack-dev-server"
},
本地安装webpack,如果webpack-dev-server想运行在本地项目中,还必须在项目中安装webpack
npm install webpack -D
执行npmrundev命令,会返回如下
从第四步我们可以看到webpack-dev-server生成的bundle.js运行在项目根目录下。 这个文件并不是存放在C盘的化学盘上,而是托管在笔记本的内存中,所以我们在项目中基本上都能看到它。 不是这个bundle.js文件,我们可以通过将index.html中的bundle.js引用路径改为项目根路径来引用这个文件
<script src="/bundle.js"></script>
可以感受到webpack-dev-server将打包后的文件以虚拟的方式托管在项目的根目录下,虽然我们看不到,但我们可以感觉到它和dist、src、nodemodule是一个级别的,还有一个不可见的文件,名为bundle.js
注意:
3.2 附加参数
webpack-dev-server不仅帮助我们实现了手动编译打包的功能,还可以添加额外的参数来帮助我们实现更强大的功能
表格1(推荐):
//package.json
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"
},
表格2(随便理解):
//webpack.config.js
const webpack = require('webpack') //引入Webpack,启用热更新的第2步
devServer:{ //设置dev-server命令参数的第二种形式,相对麻烦一些
open:true,
port:3000,
contentBase:'src',
hot:true // 启用热更新的第一步
},
plugins:[ //配置插件的节点,热更新的第2步
new webpack.HotModuleReplacementPlugin() //new 一个热更新的模块对象,这是启用热更新的第3步
]
3.3 html-webpack-插件
插件作用:
插件使用:
安装 html-webpack-plugin
npm i html-webpack-plugin -D
在 webpack.config.js 文件中添加插件
//webpack.config.js
const htmlWebpackPlugin = require('html-webpack-plugin')
plugins:[
new htmlWebpackPlugin({ //创建一个在内存中生成html页面的插件
template:path.join(__dirname,'./src/index.html'),//指定模版页面,将来会根据指定的页面路径,去生成内存中的页面
filename:'index.html'
})
]
实际显示:
扩展:-S、-D、-g 指令
npminstallmodule_name -S 为npminstallmodule_name –保存写入依赖
npminstallmodule_name -D 为npminstallmodule_name –save -dev 写入devDependencies
npminstallmodule_name -g 全局安装(命令行使用)
npminstallmodule_name 本地安装(将安装包放在./node_modules下)
依赖项和 devDependency 之间有什么区别?
四。 装载机的使用
注意:Webpack默认只能打包处理Js类型的文件,很难处理其他非Js类型的文件
如果我们要处理非Js类型的文件,我们需要自动安装一些合适的第三方loader加载器
4.1 loader处理样式表
打包处理CSS文件:安装style-loadercss-loader
npm i style-loader css-loader -D
在 webpack.config.js 配置文件中添加模块节点对象。 在这个模块对象的头部,有一个规则属性列表。 该字段存储了所有第三方文件的匹配和处理规则。
module:{ //这个节点,用来配置所有第三方模块加载器
rules:[ //配置第三方模块的匹配规则
{test:/.css$/,use:['style-loader','css-loader']} //配置处理 .css文件的第三方loader规则
]
}
在main.js入口文件上方引入CSS文件即可成功使用
import './css/index.css'
4.2 loader处理URL地址
问题描述:
解决方案:
使用步骤
安装 url-loader 文件加载器插件
在 webpack.config.js 文件上配置 URL 处理规则
//URL图片路径的匹配规则
{test:/.(jpg|jepg|png|gif)$/,use:'url-loader?limit=1000&name=[hash:8]-[name].[ext]'},
//字体图标的匹配规则
{test:/.(eot|svg|woff|woff2|ttf)$/,use:'url-loader'}
4.3 扩展:Webpack处理第三方文件类型的过程首先对文件类型进行校准。 如果是js文件,则直接打包。 如果不是js文件,获取后缀名,进入webpack。 错误报告规则的使用规则链表是从右向左调用的,前面调用的处理结果会交给后面的规则进一步处理。 调用完成后,处理结果会直接交给Webpack进行打包合并,最后输出到bundle.js
例子:
module: {
rules: [
{ test: /.css$/, use: ['style-loader', 'css-loader'] }
]
}
4.4 小结五. 巴别塔的使用
在Webpack中,默认情况下只能处理部分ES6句型。 一些更中间的 ES6 或 ES7 句型无法被 Webpack 处理。 这时候就需要使用第三方加载器来帮助Webpack处理这个中间句型,当第三方加载器将中间句型转换为低级句型时,它会将结果交给Webpack将其打包到bundle.js中
通过Babel,它可以帮助我们将中级句型转换为低级句型
5.1 安装 5.2 配置
{test:/.js$/,use:'babel-loader',exclude:/node_modules/}
在项目的根目录中,创建一个名为 .babelrc 的新 Babel 配置文件
{
"presets":["env","stage-0"],
"plugins":["transform-runtime"]
}
完成上述配置后,项目中就可以使用ES6句型了。 您可以编译一个Class类,设置静态属性并复制它们进行测试
6.在Webpack中使用Vue
传统Vue使用方法
通过 script 标签引入 vue.js 文件 在 body 中声明一个 bag,并为其设置 id 属性 通过 script 标签中的 newVue() 创建 VM 实例 6.1 包的搜索规则
当我们使用import命令导出模块中的包时,它的查找规则是什么?
查看项目目录下是否有node_modules文件夹。 在node_modules文件夹中找到对应的包名。 在package.json配置文件上,找到一个main属性【main属性指定包加载时的入口文件】
接下来我们尝试导出一个vue包webpack引入js,查看其对应的入口文件
6.2 尝试使用 Vue 和 webpack
以下是一些简单的代码模板,这里是代码说明,不做具体解释
//main.js 入口文件
//此处导入的是 vue.runtime.common.js
import Vue from 'vue'
var login = {
template:`Login success
`
}
var vm = new Vue({
el:'#app',
data () {
return {
msg:'hello'
}
},
components:{
login
}
})
//index.html
<body>
<div id="app">
<p>{{msg}}</p>
<login></login>
</div>
</body>
运行看看结果
误差分析
6.3 方案一
将模板预编译成render函数(使用render函数渲染模板)
渲染函数的使用,详细请看这里:
经过尝试,我们发现将组件写在入口文件上并不能达到目的,所以我们提取了vue模板,通过vue文件创建模板
创建login.vue文件
这是通过 vue 文件创建的模版
安装加载 .vue 文件并配置 webpack.config.js 的插件
cnpm i vue-loader vue-template-compiler -D
//webpack.config.js
const vueLoaderPlugin =require('vue-loader/lib/plugin')
plugins:[
new vueLoaderPlugin()
],
module:{
rules:[
{test:/.vue$/,use:'vue-loader'}, //处理.vue文件
]
},
在入口文件上引入login.vue,使用render函数进行渲染
import Vue from 'vue'
import login from './login.vue'
var vm = new Vue({
el:'#app',
data () {
return {
msg:'hello'
}
},
// render:function(createElement){
// return createElement(login)
// },
//简写
render:c => c(login)
})
再次运行发现运行成功
6.4 方案2
使用包含编译器构建(即完整的 vue.js 文件)
更改原来导出的vue.runtime.common.js,将导入的包更改为vue.js
更改node_modules中vue的package.json文件夹的main属性,指定为vue.js。 导入时,将导入路径改为 importVuefrom'../node_modules/vue/dist/vue.js' 或者按照原来的 import 方法 importVueform'vue',并且需要在 webpack.config.js 中减少以下配置文件
resolve:{
alias:{
"vue$":"vue/dist/vue.js"
}
}
6.5 小结 七. Webpack 中 Vue-Router 7.1 的基本使用
安装 vue-router 依赖模块
npm i vue -S
npm i vue-router -S
在main.js中引入Vue和vue-router模块,并显式调用vue-router
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
在src目录下创建App.vue主页面模板文件
APP组件
export default {
}
创建一个div元素,其id属性等于索引文件中的app
在src目录下新建文件夹,并在新建文件夹下创建login.vue和register.vue文件
将login.vue和register.vue组件应用到应用首页模板
APP组件
Login
Register
export default {
}
在main.js文件中配置路由,创建VM实例并挂载应用程序
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import app from './App.vue'
import login from './comp1/login.vue'
import register from './comp1/register.vue'
var router = new VueRouter({
routes:[
{path:'/login',component:login},
{path:'/register',component:register}
]
})
var vm = new Vue({
el:'#app',
render: c => c(app),
router
})
完成以上配置后,启动项目
7.2 路由嵌套
Webpack 中的路由嵌套与 Vue 中的路由嵌套基本类似
在基本使用路由的前提下,新建两个组件账户,money
在登录组件中添加这两个组件,并添加容器
Login success
Account
Money
在路由配置中添加children属性登录,并配置账户和资金路由。
var router = new VueRouter({
routes:[
{path:'/login',component:login,children:[
{path:'account',component:account},
{path:'money',component:money},
]},
{path:'/register',component:register}
]
})
7.3 提取路由模块
为了防止入口文件main.js内容过多,建议使用提取路由并为router创建单独文件夹的方法
7.4 组件中的style标签lang属性和scoped属性
范围属性:
语言属性:
...未完待续,持续更新
发表评论