Webpack

1. 介绍

  • 是什么
    • 打包工具
    • JavaScript 模块打包之后就可以运行在浏览器
  • 能做什么
    • webpack 可以当做是一个模块打包平台,但是它本身只能打包 JavaScript 模块
    • 对于其他的文件模块资源,则需要使用第三方 loader 来处理
    • JavaScript 资源打包
    • css 打包
    • 图片 打包
    • less
    • sass
    • babel EcmaScript 6 转 EcmaScript 5
    • 开发工具,http 服务器
    • 代码改变,自动刷新浏览器
    • 压缩代码
  • webpack 1.x
  • webpack 2.x
  • 官方指南

2. 起步

2.1 hello world

全局安装:

npm install --global webpack

准备目录结构:




foo.js文件内容如下:

module.exports = function () {
	console.log('我是 foo 文件模块啊')
}

main.js文件内容如下:

var foo = require('foo')
foo()

打包:

webpack main.js bundle.js

index.html文件内容如下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <!--<srcipt src="js/main.js"></script>-->
        <!-- 最后记得把 index.html 文件中的脚本应用改为打包之后的结果文件路径 -->
        <script src="js/bundle.js"></script>
    </body>
</html>

打开查看index.html

为了划分目录结构的清晰,所以我们把项目中的源码和打包结果做了如下划分:

  • 把源码存储到 src 目录中
  • 把打包的结果存储到 dist 目录中

2.2 安装

全局安装:

npm install --global webpack 	# 全局安装
npm uninstall --global webpack 	# 全局卸载

安装在全局的 webpack 打包的时候使用的是你安装在自己电脑上的 webpack, 如果到了另一个人的计算机上,它可能安装的是老版本的 webpack。那么就可能涉及到兼容性的问题。

而且如果对方没有在全局安装 webpack 则就无法打包。

所以,为了解决以上的问题,我们更推荐吧 webpack 安装到本地项目中。这样的话项目到哪里,webpack就跟到哪里。(打包工具随着项目走) 。

我们安装的时候把 webpack 安装到开发依赖(–save-dev)中,因为 webpack 只是一个打包工具,项目如果需要上线,上线的是打包的结果,而不是这个工具。所以了我们为了区分核心包依赖和开发工具依赖,这里通过--save--save-dev来区分。

本地安装(推荐):

npm install --save-dev webpack

对于安装到项目中的 webpack 需要配置 npm scripts 来使用。

{
    "name": "demo2",
    "version": "1.0.0",
    "description": "",
    "main": "webpack.config.js",
    "scripts": {
        "a": "node ./src/a.js",
        "b": "node ./src/b.js",
        "start": "node ./src/main.js",
        "build": "webpack"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "webpack": "^3.8.1"
    }
}

然后通过 npm run命令来打包:

npm run a

# start 比较特殊,可以不加 run
npm start

# 打包构建
# 这里使用的 webpack 就是项目中安装的 webpack
npm run build

2.3 打包JavaScript模块

2.4 配置文件 webpack.config.js

最基本的配置项:

// 该文件其实最终是要在 Node 环境下执行
const path = require('path')

// 导出一个具有特殊属性配置的对象
module.exports = {
	entry: './src/main.js', // 入口文件模块路径
	output; {
		path: path.join(_dirname, './dist/'), //出口文件模块所属目录, path 必须是一个绝对路径
		filename: 'bundle.js' // 打包的结果文件名称
	}
}


打包:

# webpack 会自动读取 webpack.config.js 文件作为默认的配置文件
# 也可以通过 --config 参数来动手指定配置文件
webpack

2.5 npm scripts

3. 打包 JavaSrcipt 模块

3.1 JavaScript 模块化

  • AMD
    • Require.js
  • CMD
    • Sea.js
  • CommonJs
  • 以上都是民间搞出来的,所以在2015年的 EcmsSript 6 中官方就发布了官方的 模块规范: EcmsScript 6 Module 模块规范
    • 我们更推荐在项目中使用 EcmaScript 6 模块规范
    • 以后的统一趋势
  • webpack
    • AMD
    • CMD
    • CommonJs
    • EcmaScript 6 Module

3.2 EcmaScript 6 模块规范

导入 import ( require )

导出 export ( module.exports )

导出默认成员:

// 默认成员只能有一个,否则报错
exports default 成员

加载默认成员:

// 如果没有 default 成员,则加载到的就是 undefined
import xxx from '模块标识'

导出多个成员:

// export 必须引用到内部的一个成员
export const a = 123
export const b = 456
export function fn () {
    console.log('fn')
}

如果你觉得上面的方式比较麻烦,也可以以这样的方式来导出多个成员:

export const a = 123
export const b = 456
export function fn () {
    console.log('fn')
}

// 注意:这一不是对象的简写方式,这是导出的特殊语法
// 这种方式也不是覆盖,后面还可以继续导出
export {
	a,
    b,
    fn
}

// 可以继续增加导出的成员
export function add (x, y) {
    return x + y
}

// 最终导出的实际上是 a, b, fn, add

按需加载指定的多个成员:

import {a, b} from '模块标识'

一次性加载所有的导出成员:

// 所有成员包含 default
import * as xxx from '模块标识'

4. 资源管理

webpack 不仅可以打包JavaScript模块,甚至它把网页开发中的一切资源都可以当做模块来打包处理。

但是它本身并不如此,它只是一个打包平台,其他资源,例如css、less、saas、img等资源需要结合插件来实现

这些插件在 webpack 中被称为 loader, 翻译过来就是 加载器 的意思。

4.1 Loading CSS

安装依赖:

# css-loader 的作用是把 css 文件转换为 JavaScript 模块
# style-loader 的作用是动态创建 style 节点插入到 head 中
npm install --save-dev style-loader css-loader

配置:

var path = require('path')

module.exports = {
	entry: './src/main.js',
	output: {
		path: path.join(__dirname, './dist'), //这里必须是绝对路径
		filename: 'bundle.js'
	},
	module: {
		rules: [
			{
                // 注意:这里的顺序很重要,不要乱了顺序,从咱们的角度,老外的思维是反的
				test: /.css$/,
				use: [
					'style-loader',
					'css-loader'
				]
			}
		]
	}
}

打包:

npm run build

解释:打包 css 也是包 css 文件内容转换成一个 JavaScript 模块,然后在运行 JavaScript 的时候,会动态地创建一个 style 节点插入到 head 头部。

4.2 Loading Images

安装依赖:

npm install --save-dev file-loader

配置:

module: {
		rules: [
			{
				test: /.css$/,
				use: [
					'style-loader',
					'css-loader'
				]
			},
			{
				test: /.(jpg|png|gif|svg)$/,
				use: [
					'file-loader'
				]
			}
		]
	}

4.3 Loading Fonts

4.4 Loading Data

4.5 Loading Less

安装依赖:

# 前提 style-loader css-loader 已经安装了,如果没有,也要加上这两个
npm install --save-dev less-loader less

4.6 Loading Sass

4.7 transpiling JavaScript

  • babel

    • http://babeljs.io/
    • babel 是一个 JavaScript 编译器,可以把 EcmaScript 6 编译成 EcmaScript 5
    • babel 可以独立使用,但是独立使用没有意义,一般是和 webpack 结合到一起来使用的
  • exclude

  • cacheDirectory

  • babel-polyfill

    • 默认 babel 只转换语法
    • 我们可以使用 babel-polyfill 来转换 EcmaScript 6 中的 API
  • babel runtime

安装依赖:

npm install --save-dev babel-loader babel-core babel-preset-env

配置:

module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/, // 不转换 node_modules 中的文件模块
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['env']
                }
            }
        }
    ]
}

4.7.1 配置 babel-polyfill 来提供低版本浏览器中的不支持API

安装依赖

npm install --save-dev babel-polyfill

配置:

entry: ['babel-polyfill', './src/main.js'],

这样的话就会在打包的结果中提供一个踮脚片用以兼容低版本浏览器中的不支持的API。

4.7.2 配置 transform-runtime 来解决代码重复问题

在打包过程中, babel 会在某给包提供一些工具函数,而这些工具函数可能会重复的出现在多个模块。这样的话就会导致打包体积过大,所以 babel 提供了一个 babel-transform-runtime 来解决这个打包体积过大的问题。

安装:

npm install --save-dev babel-plugin-transform-runtime
npm install --save babel-runtime

配置:


4.7.3 加入缓存节省编译时间

babel 编译是非常耗时的,我们可以通过开启对编译结果的缓存来提高打包速度:

module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /(node_modules | bower_components)/,
            use: {
                loader: {
                    // 默认把打包的结果缓存到 node_modules/.cache 目录
                    cacheDirectory: true,
                    preserts: ['env'],
                    plugin: ['transform-runtime']
                }
            }
        },
    ]
}

5. 输出管理

5.1 HtmlWebpackPlugin

你会发现,当你打包结束的时候,如果 index.html 在根目录直接运行的话,那么图片资源这些路径就无法访问到了。解决方案就是把 index.html 放到 dist 目录中。

但是 dist 是打包编译的结果,而非源码,所以把 index.html 放到 dist 就不合适。

而且你也会发现,我们打包的结果文件名: bundle.js, 如果一旦我把这个文件名给改了,则 index.html 也要手动修改。

综合以上我们遇到问题,我们就可以使用一个插件,html-webpack-plugin 来解决。

安装依赖:

npm install --save-dev html-webpack-plugin

配置:

	plugins: [
		// 该插件的作用就是把 index.html 打包到你的 bundle.js 文件所属目录
		// 也就是说 bundle 到哪里,index.html 就到哪里
		// 同时这个也会自动在 index.html 中注入 script 引用链接
		// 而且引用的资源名称,也取决于你的 bundle 叫什么
		// 这个插件还可以配置压缩 html 的处理
		new htmlWebpackPlugin({
			template: './index.html'
		})
	],

5.2 CleanWebpackPlugin

6. Develoment开发

6.1 Source maps

6.2 webpack-dev-server

每一次手动打包很麻烦,而且即便有--watch也不方便,还需要自己手动刷新浏览器

所以 webpack 给你提供了一个工具,webpack-dev-server

它就可以时间监视代码改变,自动打包,打包完毕自动刷新浏览器的功能。

安装依赖:

npm install --save-dev webpack-dev-server

配置:(没有说明,默认都是在根级配置)

	devServer: {
		// 配置 webpack-dev-server 的 www 目录
		contentBase: './dist'
	},

配置 npm scripts:

  "scripts": {
    "build": "webpack",
    "watch-build": "webpack --watch",
    "dev": "webpack-dev-server --open"
    // 启动服务器,打包,自动打开浏览器
	// 当打包结束后,自动打开浏览器
  },

启动开发模式:

npm run dev

解释: 该工具惠自动帮你打包,打包完毕只有会自动开启一个服务器,默认监听8080端口号,同时自动打开浏览器让你访问,接下来就会自动监视代码的改变,然后自动编译,编译完毕,自动刷新浏览器

6.3 ESLint代码规范校验

  • eslint
  • eslint-loader
  • eslint-plugin-html
  • 安装
  • 初始化 .eslintrc.js 配置文件
  • 配置到 webpack

7. Hot Module Replacement 热更新

const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
+++ const webpack = require('webpack')

module.exports = {
    entry: ['babel-polyfill', './src/main.js'],
    output: {
        path: path.join(__dirname, './dist/'), // 这里必须是绝对路径
        filename: 'bundle.js'
    },
    plugin
}

8. Vue Loader

打包.vue单文件组件的

Vue单文件组件

  • vue-loader
  • vue-template-compiler

安装依赖:

# vue-loader 依赖 vue-template-compiler
npm install --save-dev vue-loader vue-template-compiler

配置:

module: {
    rules: [
        {
                test: /.vue$/,
                use: [
                    'vue-loader'
                ]
            }
    ]
}
  • css-loader
  • file-loader

9. Resolve

9.1 alisa

9.2 extensions

10. externals

配置 webpack 不打包第三方包

通常情况下我们不打包第三方包,因为第三方包太大,和 bundle 打包到一起会造成资源体积过大,所以我们还是通过 script 标签的方式把第三方资源引入到页面中,只需要通过以下配置即可,这里以 jQuery 为例

  1. 下载第三方包
npm install jquery
  1. 在页面中引入资源
<!-- 注意:这里的路径以打包后的 index.html 文件位置为准 -->
<script src="../node_modules/jquery/dist/jquery.js"></script>
  1. 配置
externals: {
    // key 是第三方包名称, value 是全局中的 jquery 对象
    // 这里配置的含义就是:当你在代码中 import jquery 的时候,不会把 jquery 打包到 bundle 中,而是使用我指定的全局中的 jQuery 对象
    jquery: 'jQuery'
}
  1. 加载使用
import $ from 'jquery'

$('#app', {
    width: 200,
    height: 200,
    backgroundColor: 'pink'
})
  1. 打包测试
npm run build

11. --save--save-dev的区别

我们把开发工具相关的依赖信息保存到 devDependencies 选项中。把核心依赖 (例如 vue ) 的依赖信息保存到 dependencies 选项中。

这样做的话,就是把开发依赖和核心依赖分开了,因为开发依赖在打包结束之后上线的话就不需要。

最后项目上线,我们真正需要安装发布的是 dependencies 依赖项中的包。

我们可以通过命令来只安装 dependencies 依赖项中的包:

npm install --production

单文件组件高亮

https://github.com/vuejs/vue-syntax-highlight

21. vue-webpack-starter

12.1 在模块化环境中使用 vue-router

  1. 下载
npm install vue-router
  1. 引用资源
<script src="node_modules/vue-router/dist/vue-router.js"></script>
  1. 配置 externals
externals: {
    'vue-router': 'VueRouter'
}
  1. router.js 文件中加载使用
import VueRouter from 'vue-router'
import Foo from './components/Foo.vue'
import Bar from './components/Bar.vue'

// 这里直接默认导出 new 出来的 router 实例
export default new VueRouter({
    routes: [
        {
            path: '/foo',
            component: Foo
        },
        {
            path: '/bar'
            component: Bar
        }
    ]
})

  1. main.js 文件中配置使用路由对象
import Vue from 'vue'
import App from './App.vue'
+++ import router from './router'

new Vue({
    components: {App},
    template: '<App />'
    router
}).$mount('#app')

  1. App.vue 中设置路由出口
<template>
<div id="app">
	<h1>根组件 hh</h1>
	<ul>
		<li><a href="#/foo">Go to Foo</a></li>
		<li><a href="#/bar">Go to Bar</a></li>
	</ul>
	+++ <router-view></router-view>
</div>
</template>

12.2 引入 bootstrap 样式库

  1. 安装
npm install bootstrap
  1. 引入到 index.html
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.css">

13. VueCLi

Vue作者考虑到新手使用 webpack 带来的复杂度,所以官方开发了一个工具: vue-cli 它可以帮你快速生成一个已经配置好了 webpack 项目。

但是我们不用它,用了它你就是傻瓜,遇到问题你不会解决。

14. async函数

参考链接

http://es6.ruanyifeng.com/#docs/async

posted on 2021-06-16 21:34  beyondx  阅读(31)  评论(0编辑  收藏  举报

导航