从零开始学webpack(v5.0)

642 阅读12分钟

webpack静态模型快打包工具

webpack.docschina.org/

webpack是一个现代JavaScript应用程序的静态模块打包工具

当webpack处理应用程序时,它会在内部构建一个依赖图(dependency [/dɪˈpendənsi/] graph [/ɡræf/]),此依赖图会映射项目所需的每个模块,并生成一个或多个bundle包!webpack本身是基于node.js开发的!

webpack是大前端时代下,实现项目的工程化和自动化的工具。

还有几个打包工具:grunt、gulp、fis、webpack、snowpack、vite...

为啥使用webpack

  • 代码转换:TypeScript编译成JavaScript、LESS/SCSS编译成CSS、ES6/7编译为ES5、虚拟DOM编译为真实的DOM等等…
  • 文件优化:压缩JS、CSS、HTML代码,压缩合并图片,图片BASE64等
  • 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码等
  • 模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件
  • 自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器
  • 代码校验:Eslint代码规范校验和检测、单元测试等
  • 自动发布:自动构建出线上发布代码并传输给发布系统

1.CommonJs规范 & ES6Module规范

模块化变成进化历史

  • 单例设计模式
  • AMD [require.js]
  • CommonJs
  • CMD [sea.js]
  • ES6Module

1) 单例设计模式

特点:单例设计模式作为早期的的模块化编程方案,是可以实现模块区分的,避免全局变量污染的;但是随着前端的发展,我们要拆分的模块越来越多,而且模块和模块之间的依赖也越来越复杂,单例模式在处理模块依赖的时候,容易把人搞"疯"!

  • 在html中引入JS文件需要根据依赖顺序,以此导入

image.png

image.png

let xxxModule = (function () {
    let time = new Date();
    const query = function query() {
        // ...
    };
    const handle = function handle() {
        // ...
    };

    // 把供其它板块调用的方法,暴露到全局对象上
    //「局限:暴露的内容比较多,则还会引发全局变量冲突」
    // window.query = query;

    return {
        query,
        handle
    };
})();

2)AMD模块「require.js

require.js是AMD模块化思想:按需导入,依赖管理

  • AMD思想的一个问题:所有依赖的模块都需要前置导入
  • 好处: 各模块进行管理
  • ['模块路径']
  • 依赖模块 require(['依赖模块A','B',...],function(A,B,...){ })
  • 定义模块 define(function(){ })
  • 定义加依赖模块 define(['依赖模块A','B',...],function(A,B,...){ })

image.png

image.png

image.png

//main.js
require.config({
    //全局配置
    baseUrl: 'js/lib',
});

require(['moduleB', 'moduleA'], function (moduleB, moduleA) {
    console.log(moduleB.average(10, 20, 30, 40, 50));
});

//moduleA.js
define(function () {
    return {
        sum(...args) {
            let len = args.length,
                firstItem = args[0];
            if (len === 0) return 0;
            if (len === 1) return firstItem;
            return args.reduce((total, item) => {
                return total + item;
            });
        }
    };
});

//moduleB.js
define(['moduleA'], function (moudleA) {
    return {
        // 求平均数(去掉最大最小值)
        average(...args) {
            let len = args.length,
                firstItem = args[0];
            if (len === 0) return 0;
            if (len === 1) return firstItem;
            args.sort((a, b) => a - b);
            args.pop();
            args.shift();
            return (moudleA.sum(...args) / args.length).toFixed(2);
        }
    };
});

3)CommonJS模块 [现在我们还可以使用]

优点:随导随用

CommonJS模块规范

  • 导出 module.exports
  • 导入 require('./模块地址') module.exports = {};
  • let obj = require('./模块地址');
  • let {sum} = require('./模块地址');【直接解构赋值】 module.exports = xxx;
  • let xxx = require('./模块地址'); 导入自己写的模块需要加“./”这样的地址,如果是导入Node内置模块(或者安装的第三方模块),直接写模块名字即可!!

特点:只能在Node环境下运行,不能在浏览器端运行

淘宝“玉伯”之前开发过一款插件sea.js,旨在让浏览器端也能运行CommonJS模板规范,他把这种模块思想称之为“CMD”

现在sea.js已经不用了,但是我们使用webpack打包的时候,webpack是支持commonJS规范的,所以我们可以直接使用commonJS规范写代码,最后webpack帮我们编译为浏览器可以识别的代码!

image.png

image.png

/* ---A.js--- */
const sum = function sum(...params) {
    return params.reduce((result, item) => {
        return result + item;
    });
};
// 暴露一些API
module.exports = {
    sum
};


/* ---B.js--- */
let name = '哈哈';
let A = require('./A');
const average = function average(...params) {
    return (A.sum(...params) / params.length).toFixed(2);
};
module.exports = {
    average
};


/* ---main.js--- */
let A = require('./A');
console.log(A.sum(10, 20, 30, 40));
let B = require('./B');
console.log(B.average(10, 20, 30, 40));

4)ES6Module模块

ES6Module中的模块导入导出规范【export或者export default导出,import导入】

导入import,必须写在模块的最开始

type="module"直接在浏览器端开启ES6Module规范;并且需要保证页面是基于http或者https协议【Open with Live Server】 <script type="module" src="main.js"></script>

1.导出:export

export const n = 100;

export const m = 200;

1.导入:import

import * as A from './A.js'

使用的时候:A.n 、 A.m

2.导出【export default只能用一次】

export default 对象/函数

export default { sum,func }

2.导入

import A from './A.js'

3.导出 export default function sum(){ }

3.导入 import sum from ./A.js'

同一个模块中,“export default”只能用一次

  • export {xxx : xxx};

webpack环境下既支持CommonJS规范,也支持ES6Module规范,而且可以支持两者混着用【用CommonJS规范导入,用ES6Module规范导出...】

image.png

image.png

image.png

A.JS
// 单例模式实现模块化
const sum = function sum(...params) {
    let len = params.length;
    if (len === 0) return 0;
    if (len === 1) return params[0];
    return params.reduce((result, item) => {
        return result + item;
    });
};
//export default sum;
export default{
    sum
};

B.JS
import A from './A.js';
// 浏览器端使用ES6Module,'.js'不能忽略 [webpack中使用可以忽略后缀名]
const average = function average(...params) {
    let total = A.sum(...params);
    return (total / params.length).toFixed(2);
};
export default average;

main.js
// import 只能放在最开始的位置
import A from './A.js';
import average from './B.js';
console.log(A.sum(12,23,34,45));
console.log(average(12,23,34,45));

index.html
<!-- 
    type="module" 直接在浏览器端开启ES6Module规范
    并且需要保证页面是基于HTTP/HTTPS协议预览 [Live Server]
 -->
<script type="module" src="main.js"></script>
  • 支持export导出多个"导入方式"
c.js
export let n = 100;
export let m = 200;
export const fn = function fn() { };

main.js
// 支持export导出多个"导入方式"
import * as C from './C.js';
console.log(C);

/* import { n, m, fn } from './c.js';
console.log(n, m, fn); */

image.png

  • 支持export default函数
D.js
export default function () {
    console.log('fn');
};

main.js
//支持 export default 函数
import fn from './D.js';
console.log(fn); 
  • 支持 export default 对象
E.js
const fn = function fn() { };
const sum = function sum() { };
export default {
    fn,
    sum
};

main.js
//支持 export default 对象
import E from './E.js';
//浏览器端,此种方案:不能直接import的时候给E解构赋值,但是获取到E后,可以单独自己解构
// const {sum,fn}=E
console.log(E);

image.png

/* ---index.html--- */
<!-- 
   type="module" 让浏览器支持ES6Module规范
   必须是基于HTTP/HTTPS协议预览
-->
<script type="module" src="main.js"></script>

/* ---main.js--- */
/* 导入,必须写在模块的最开始 */
import A from './A.js';
import average from './B.js';
console.log(A.sum(10, 20, 30, 40));
console.log(average(10, 20, 30, 40));

/* ---A.js--- */
const sum = function sum(...params) {
    return params.reduce((result, item) => {
        return result + item;
    });
};

// 分别导出多个
// export const AA = 'xx';
// export const BB = 'xx';

// 导出一个
// export default sum;
export default {
    sum
};

/* ---B.js--- */
import A from './A.js';
const average = function average(...params) {
    return (A.sum(...params) / params.length).toFixed(2);
};
export default average;

2.NPM的操作阶段

  • 安装在 全局 & 本地 的区别
  • 安装在本地如何使用命令
  • npx 「npm > 5.2」

3.webpack的操作基础

1)安装

想用webpack必须提前安装:webpack webpack-cli

  • 1.安装在全局npm i webpack webpack-cli -g
    • 卸载:npm uninstall webpack webpack-cli -g
    • 能直接使用命令webpack
    • 所有项目都用相同版本的webpack;但是如果想用不同版本的webpack是不容易实现【容易引起版本冲突】
  • 2.安装在当前项目中npm i webpack webpack-cli --save-dev
    • 或者yarn add webpack webpack-cli -D
      • 使用yarn之前需要先执行yarn init -y生成package.json文件
    • 不能直接使用webpack命令
    • 每个项目有自己单独版本,不会导致版本冲突 ---------------------- 如何实现:安装在本地项目中,但是也可以使用命令进行打包?
  • 1.当npm版本 > 5.2,直接使用npx运行对应的命令即可 $ npx webpack
  • 2.在package.json中配置可执行的脚本命令
"scripts": {    
  // 脚本名字:要执行的命令 [前提:在node_modules目录的.bin文件夹下,需要有webpack这个命令文件]
  "build":"webpack"
}
  • npm run build 【npm run 配置的脚本名字】

image.png

2)零配置使用

npm run build 默认查找根目录下的src文件夹下的index.js文件;默认打包完成的目录为:dist目录下的main.js

image.png

 * 默认会打包SRC目录中的JS文件(入口默认index.js)
 * 打包完成的目录默认是DIST/MAIN.JS
 * webpack默认支持CommonJS和ES6 Module的模块规范,依此进行依赖打包
 */
$ npx webpack

3)自定义基础配置

webpack.config.js || webpackfile.js

const path = require('path');

module.exports = {
    // 设置打包模式 development:开发模式 production:生产模式[默认]
    // 开发模式下的特点是:默认不压缩
    // 生产模式下的特点是:默认压缩
    mode: 'development',
    // 打包入口文件目录
    entry: './src/main.js',
    // 打包后的输出目录
    output: {
        // 输出文件名
        filename: 'bundle.js',
        // 输出的路径 [必须是一个绝对路径]
        path: path.resolve(__dirname,'dist')
    }
};

image.png

  • development 开发模式 [默认不压缩]

image.png

  • production 生产模式 [默认压缩]

image.png

4)自定义配置文件名

执行webpack命令

  • 自己不写 webpack.config.js,则默认找 src/index.js 打包输出到 dist/main.js
  • 如果自己写了 webpack.config.js,则按照自己写的规则出来
  • 真实项目中,往往是我们需要自己去区分环境 [开发环境 & 生产环境],两个环境走不同的配置 指定webpack打包时候,查找的规则文件
  • @1 创建不同的规则文件
    • webpack.config.development.js 【开发环境的打包规则】
    • webpack.config.production.js 【生产环境的打包规则】
  • @2 配置不同的脚本命令,执行某个命令,让其走自己对应的规则
scripts": {
    "serve": "webpack --config webpack.config.development.js",
    "build": "webpack --config webpack.config.production.js"
  }
  • $ npx webpack –config webpack.config.development.js
  • 可在package.json中配置可执行的脚本命令(区分开发环境)

image.png webpack.config.js

const path = require('path');

module.exports = {
    // 设置打包模式 development:开发模式 production:生产模式[默认]
    // 开发模式下的特点是:默认不压缩
    // 生产模式下的特点是:默认压缩
    mode: 'production',
    // 打包入口文件目录
    entry: './src/main.js',
    // 打包后的输出目录
    output: {
        // 输出文件名
        filename: 'bundle.js',
        // 输出的路径 [必须是一个绝对路径]
        path: path.resolve(__dirname,'dist')
    }
};

webpack.config.development.js 开发环境

/* 开发环境的打包规则 */
const path = require('path');
module.exports = {
    mode: 'development',
    entry: './src/main.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname,'dist')
    }
};

webpack.config.production.js 生产环境

/* 生产环境的打包规则 */
const path = require('path');
module.exports = {
    mode: 'production',
    entry: './src/main.js',
    output: {
        // [hash]:每一次打包的时候,根据文件内容不同,生成不同的HASH值,保证文件代码更新,生成的文件名字是不同的
        filename: 'bundle.[hash].min.js',
        path: path.resolve(__dirname,'dist')
    }
};

image.png

image.png

5)使用插件打包 HtmlWebpackPlugin

  • 在src文件夹下新建一个index.html,然后去webpack.config.js中写配置
  • $ npm i html-webpack-plugin -–save-dev
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    ...,
    //=>在webpack中使用插件
    plugins: [
        new HtmlWebpackPlugin({
            //=>指定自己的模板
            template: './src/index.html',
            //=>输出的文件名
            filename: 'index.html',
            //=>给引入的文件设置HASH戳(清除缓存的),也可以在output中设置 filename: 'bundle.[hash].js' 来生成不同的文件
            hash: true,
            //=>控制是否以及以何种方式最小化输出 
            //=>https://github.com/kangax/html-minifier
            minify: {
                collapseWhitespace: true,
                removeComments: true,
                removeAttributeQuotes: true,
                removeEmptyAttributes: true
            }
        })
    ]
}

image.png

6)清除打包工具 CleanWebpackPlugin

  • 每一次打包工具之前,要清除之前打包的内容
  • $ npm i clean-webpack-plugin –save-dev
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports={
    plugins:[
        new CleanWebpackPlugin()
    ]
};

image.png

7)配置webpack-dev-server

  • $ npm install webpack-dev-server –save-dev
  • 配置DEV-SERVER:创建一个本地服务,实时预览编译后的内容 [开发环境下需要]
  • npm run serve:自动打开浏览器,实时监听代码更新状态,当代码变化的时候,页面会自动刷新
  1. $ npm run serve -> webpack server 【开发环境】
  • 按照规则打包编译【把编译后的文件放在内存中{临时的地方},没有放在dist目录下】
  • webpack-dev-server插件,帮助我们启动一个web服务【按照devServer配置的规则来处理】,而服务访问的内容就是去内存中查找
  • 代码修改后,启动的服务会自动监听代码改变,重新进行编译,并且通知浏览器自动更新
  1. $ npm run build -> 'webpack' 【生产环境】
  • 按照规则打包编译,把编译后的文件输出到dist目录中
  • 真实开发中,我们会把dist打包后的内容部署到服务器上

image.png

/* webpack.config.js */
//=>配置DEV-SERVER
devServer: {
    //=>端口
    port: 3000,
    host: '127.0.0.1',
    //=>开启GZIP压缩
    compress:true,
    //=>显示编译进度
    progress: true,
    //=>指定访问资源目录
    contentBase: path.resolve(__dirname, "dist"),
    //=>自动打开浏览器
    open: true,
    //=>开启热更新
    hot:true,
    //=>请求代理
    proxy:{
       "/":{
          target:"http://localhost:8888", 
          secure: false, //若为true则表示是https,false是http
          changeOrigin: true //把请求头当中的host值改成服务器地址
       } 
    }
}

/* package.json */
"scripts": {
    "serve": "webpack server",
    "build": "webpack"
}

4. webpack中的加载器loader:处理样式的

$ npm i css-loader style-loader less less-loader autoprefixer postcss-loader –save-dev

  • less sass stylus 前端样式预编译语言
    • less less-loader 编译less代码处理成css代码的
    • sass sass-loader
    • css-loader 解析CSS「@import url...」导入外部资源的代码
    • style-loader 把CSS样式插入到 head中【内嵌式】
    • less less-loader 编译less代码的
    • autoprefixer postcss-loader 自动加前缀【-webkit-、-moz-、-ms-、-o-】根据浏览器兼容问题
      • -webkit-transition:.5s;
      • -ms-transition:.5s;
      • -moz-transition:.5s;
      • -o-transition:.5s;
      • transition:.5s;
module.exports = {
//=>配置模块加载器LOADER
    module: {
//=>模块规则:使用加载器(默认从右向左执行,从下向上)
        rules: [{
            test: /\.(css|less)$/, //=>基于正则匹配哪些模块需要处理
            use: [
                "style-loader", //=>把CSS插入到HEAD中
                "css-loader", //=>编译解析@import/URL()这种语法
                "postcss-loader", //=>设置前缀
                {
                    loader: "less-loader",
                    options: {
//=>加载器额外的配置
                    }
                }
            ]
        }]
    }
}

postcss.config.js

module.exports = {
    plugins: [
require('autoprefixer')
    ]
};

package.json

// https://github.com/browserslist/browserslist
"browserslist": [
"> 1%",
"last 2 versions"
]

1) mini-css-extract-plugin 抽离CSS内容

www.npmjs.com/package/min…

  • $ npm i mini-css-extract-plugin –save-dev
  • mini-css-extract-plugin 抽离CSS内容
const MiniCssExtractPlugin=require('mini-css-extract-plugin');
module.exports = {
    plugins: [
        //=>使用插件
        new MiniCssExtractPlugin({
            //=>设置编译后的文件名字
            filename: 'main.[hash].css'
        })
    ],
    module: {
        rules: [{
            test: /\.(css|less)$/,
            use: [
                // "style-loader",
                //=>使用插件中的LOADER代替STYLE方式
                MiniCssExtractPlugin.loader,
                "css-loader",
                "postcss-loader",
                "less-loader"
            ]
        }]
    }
}

5. 设置优化项压缩CSS/JS

$ npm i optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin terser-webpack-plugin –save-dev

const UglifyjsWebpackPlugin=require('uglifyjs-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin= require('optimize-css-assets-webpack-plugin');

module.exports = {
    //=>设置优化项
    optimization: {
        //=>设置压缩方式
        minimizer: [
            //=>压缩CSS(但是必须指定JS的压缩方式)
            new OptimizeCssAssetsWebpackPlugin(),
            //=>压缩JS
            //new UglifyjsWebpackPlugin({
                //cache: true, //=>是否使用缓存
                //parallel: true, //=>是否是并发编译
                //sourceMap: true, //=>启动源码映射(方便调试)
            //}),
            new TerserPlugin()
        ]
    }
};

6. webpack中图片的处理

$ npm i file-loader url-loader html-withimg-loader –save-dev

module.exports = {
    module: {
        //=>模块规则:使用加载器(默认从右向左执行)
        rules: [{
            test: /\.(png|jpe?g|gif)$/i,
            use: [{
                //=>把指定大小内的图片BASE64
                //=>不在指定范围的采用file-loader进行处理
                loader: 'url-loader',
                options: {
                    limit: 200 * 1024,
                    outputPath:'/images', // 在dist中输出images
                    //name:'[name].[ext]' // 不把图片进行混淆,该是什么名字就是什么名字,该是什么后缀还是什么后缀,不加这个配置,可以防止盗图也防止图片冲突,也可以防止缓存。「默认为混淆处理」
                }
            }],
            include: path.resolve(__dirname, 'src'), // 编译的时候,我只对那个文件夹下的进行编译
            exclude: /node_modules/ //排除那个目录一定不编译
        }, {
        //字体图标,没有办法进行base64,但是可以使用file-loader处理
        test:/\.(svg|eot|ttf|woff|woff2)$/i,
        use:"file-loader"
        }, {
        	  //html中的image也进行处理
            test: /\.html$/,
            use: ['html-withimg-loader']
        }]
    }
}

7. 基于babel实现ES6的转换

babeljs.io/

npm i babel-loader @babel/core @babel/preset-env 核心这是哪个 @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime –save-dev npm i @babel/runtime @babel/polyfill需要下载生产环境

  • babel-loader @babel/core @babel/preset-env 核心这三个
  • rules 中继续添加{test: /.js$/, use: [{ loader: 'babel-loader',//使用加载器 babel-loader 然后用options配置项 options: { presets:["@babel/preset-env"] } }] }
    • options: { presets:["@babel/preset-env"] } 通过这个语法包把es6转译成es5
    • 但是只能转换一些语法类操作,对于很多es6内置的API无法转换
      • npm i @babel/runtime @babel/polyfill 需要下载在生产环境
      • 在main.js中通过 import '@babel/polyfill' 导入
      • 把es6无法转化的Promise,它主要是自己写了一个原生Promise。后面我们再使用就是用的人家写好的
      • 如果在项目中要兼容IE10、11 除了需要用到@babel/preset-env这个语法包,还需要把内置的API进行转化
      • 如果需要实现内置API的兼容,我们需要在程序中导入@babel/polyfill 「这个包把ES6内置的API自己实现了一遍」
module.exports = {
    module: {
        rules: [{
            test: /\.js$/,
            use: [{
                loader: 'babel-loader',
                options: {
                    //=>转换的语法预设(ES6->ES5)
                    presets: [
                        "@babel/preset-env"
                    ],
                    //=>基于插件处理ES6/ES7中CLASS的特殊语法
                    plugins: [
                        ["@babel/plugin-proposal-decorators", {
                            "legacy": true
                        }],
                        ["@babel/plugin-proposal-class-properties", {
                            "loose": true
                        }],
                        "@babel/plugin-transform-runtime"
                    ]
                }
            }],
            //=>设置编译时忽略的文件和指定编译目录
            include: path.resolve(__dirname, 'src'),
            exclude: /node_modules/
        }]
    }
}

8. 多入口 & 多出口

const htmlPlugins = ['index', 'login'].map(chunk => {
    return new HtmlWebpackPlugin({
        template: `./${chunk}.html`,
        filename: `${chunk}.html`,
        hash: true,
        chunks:[chunk,'jquery'],
        minify: {
            collapseWhitespace: true,
            removeComments: true,
            removeAttributeQuotes: true,
            removeEmptyAttributes: true
        }
    });
});
module.exports={
    entry: {
        index: "./src/index.js",
        login: "./src/login.js",
        jquery:"./src/jquery.js"
    },
    output: {
        filename: "[name].[hash].js",
        path: path.resolve(__dirname, "dist")
    },
    plugins:[
        ...htmlPlugins
    ]
};

脚手架vue/cli

  • 1.脚手架: vue->@vue/cli react->create-react-app
  • 2.基于脚手架创建项目,会默认帮我们把所有的webpack配置项设置好
  • 3.vue vue-cli老版本 @vue/cli 新版本
  • 4.npm i @vue/cli -g 全局安装vue/cli
  • 5.vue create xxx 名字「不能出现中文和特殊符号以及大写字母」

  • 1.@vue/cli是vue框架的“脚手架”【基于脚手架创建的项目,会帮我们把webpack配置好】
  • 2.默认处理:
    • 安装了vue模块
    • 完成了webpack的常规配置【模式、入口、出口、加载器、插件、优化项...】
    • 支持ESLint语法检测:编写的代码不符合语法规范,编译的时候会报错
  • 3.默认把webpack配置文件放在了node_modules中了
    • npm run serve执行vue-cli-service serve这个命令
      • 编译打包代码【放在内存中】
      • 基于webpack-dev-server启动一个web服务,运行编译的内容
      • 支持热更新,代码修改后,及时编译,实时刷新浏览器预览
    • npm run build执行vue-cli-service build这个命令
      • 编译打包代码
      • 放在dist目录下
  • 4.如何自己修改默认配置项?
    • 根目录创建 vue.config.js
      • publicPath 前缀 是根目录还是当前目录 / 是根目录
      • outputDir 打包放在那个文件下
      • lintOnSave: false eslint是否开启
      • productionSourceMap
        • 加map 为了报错可以知道是哪里报错,但是打包编译速度会变慢 不方便调试
  • 5.处理浏览器兼容
    • package.json 根据兼容浏览器:设置css前缀 & 实现JS语法转换
    • polyfills
// package.json
"browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]

vue中的package.json

image.png

文件目录

  • node_modules 安装的模块
  • public 页面的模板,多个页面开发就写多个模版
    • favicon.ico 头部图标
    • index.html 首页的模版
      • <%= BASE_URL %> 指的是public这个目录,最后要经过webpack编译
      • <%= htmlWebpackPlugin.options.title %> 页面的title可以webpack配置项中指定
    • ......

image.png

  • 为什么el的指定模板不能使用html/body?
    • 因为可以new Vue很多次但是html/body只有一个。
  • index.html模板页面中,我们可能会自己导入一些资源或者写一些代码,这些东西不想最后和其他组件中的样式和代码打包合并在一起。「打包在一起太大了,我们想提前加载和渲染我们写的这些代码,或者直接写成内嵌式,减少页面白屏」
  • 例如:
    • 把动态计算rem和px换算比例的代码单独写在这里,优先加载
    • 因为打包后的文件较大,加载需要一些时间,而等待加载的过程会出现白屏效果,此时我们可以写一些Loading或者骨架屏的代码。「客户端loading」 给用户人性化的体验,「减少白屏时间」
    • ......
  • 因为webpack中是基于ES6Module或者CommonJs规范实现导入导出和打包的,如果我们的JS不支持这两个规范,这样就无法在webpack中使用,只能基于

image.png

第一次写,如果有什么不足或者有错的地方,希望大家多多提点!谢谢(* ̄︶ ̄)