webpack css按需加载-使用 webpack 项目按需引入打包

序言

如今,大多数项目打包都是用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 并选择 源 选项以查看我们的打包文件,如下所示:

webpack css按需加载

图片.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()。

webpack css按需加载

怎么办?此时,另一个包@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: []
                // }
            }
        ]
    }

webpack css按需加载

创建一个 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

webpack css按需加载

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引入js_引入尘埃_js中引入js

目标:使用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命令,会返回如下

js中引入js_webpack引入js_引入尘埃

从第四步我们可以看到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

js中引入js_webpack引入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属性

范围属性:

语言属性:

...未完待续,持续更新