一、webpack 打包 JS 文件
-
通过
npm install webpack
命令可以下载webpack
,通过npm install webpack-cli -g
命令下载webpack-cli
。 -
创建一个空文件,在里面创建
sum.js
文件,采用ES6 module
的规范,进行求和,代码如下所示:
export default function (a, b) {
return a + b
}
- 在里面创建
minus.js
文件,采用CommonJS
的规范,进行求差,代码如下所示:
module.exports = function (a, b) {
return a - b
}
- 在里面创建
muti.js
文件,采用AMD
的规范,进行求积,代码如下所示:
define(function (require, factory) {
'use strict';
return function(a, b) {
return a * b
}
})
- 在里面创建
app.js
文件,分别进行引入并且打印,代码如下所示:
// es module
import sum from './sum'
// commonJS
var minus = require('./minus')
console.log('sum(12, 24) =', sum(12, 24))
console.log('minus(30, 24) =', minus(30, 24))
// amd
require(['muti'], function (muti) {
console.log('muti(4, 8) =', muti(4, 8))
})
- 在里面创建
index.html
文件,创建webpack.config.js
文件,使用commonJS
规范,配置entry
入口文件和output
出口文件,代码如下所示:
module.exports = {
entry: {
app: '/app.js'
},
output: {
filename: '[name].[hash:5].js'
}
}
- 通过
webpack --config webpack.conf.js
可以进行打包 JS 文件。如果是需要对于某一个单独的JS
文件打包,可以使用webpack entry<entry> output
命令,第一个参数是入口文件,第二个参数是出口文件。
二、webpack 打包 ES6 文件
- 创建一个空文件,通过
npm init
命令创建一个package.json
文件,在里面创建一个app.js
文件,代码如下所示:
import 'babel-polyfill'
let func = () => {}
const NUM = 40
let arr1 = [1, 2, 3]
let arr2 = arr1.map(item => item*2)
console.log('new Set(arr2)=' + new Set(arr2))
- 创建一个
webpack.config.js
文件,使用commonJS
规范module.exports
。entry
是配置入口文件,output
是配置出口文件。在module
中,配置rules
,配置规则,里面是数组。在rules
中,test
表示值,可以用一个正则来表示。use
表示处理使用,loader
表示使用的一些编译,可以使用babel-loader
;options
表示指定的参数,presets
表示预设, 指定规范的语法,可以使用@babel/preset-env
,targets
表示指定的目标,所支持运行环境的对象。exclude
表示排除在规则之外,比如就是node_modules
,代码如下所示:
module.exports = {
entry: {
app: './app.js',
common: [
`babel-polyfill`
]
},
output: {
filename: '[name].[hash:8].js'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
chrome: '52'
}
}]
]
}
},
exclude: '/node_modules/'
}
]
}
}
-
通过
webpack --config webpack.conf.js
可以进行打包ES6
文件。 -
通过
npm install –save-dev babel-loader babel-core
命令下载babel-loader
,通过npm install babel-preset-env –save-dev
或者是npm install @babel/preset-env –save-dev
命令下载babel-preset
。 -
babel
默认只转换新的JavaScript
语法,不转换新的API
以及一些定义在全局对象上的方法,如果想使用这些新的对象和方法,则需要为当前环境提供一个垫片polyfill
。在Babel
执行编译的过程中,会从项目的根目录下的.babelrc
文件中读取配置。.babelrc
是一个json
格式的文件。在.babelrc
配置文件中,主要是对预设(presets)
和 插件(plugins)
进行配置。 -
babel-polyfill
-
babel-polyfill
解决了Babel
不转换新API
的问题,但是直接在代码中插入帮助函数,会导致污染了全局环境,并且不同的代码文件中包含重复的代码,导致编译后的代码体积变大。虽然这对于应用程序或命令行工具来说可能是好事,但如果你的代码打算发布为供其他人使用的库,或你无法完全控制代码运行的环境,则会成为问题。 -
polyfill
包括了core-js
和regenerator-runtime
(转义async
和await
的包),最常用的配合Babel
一起使用的polyfill
是babel-polyfill
,通过改写全局prototype
的方式实现,它会加载整个polyfill
,针对编译的代码中新的API
进行处理,并且在代码中插入一些帮助函数,比较适合单独运行的项目。
- babel-runtime
-
babel-runtime
插件能够将这些工具函数的代码转换成require
语句,指向为对babel-runtime
的引用。每当要转译一个api
时都要手动加上require('babel-runtime')
。简单说babel-runtime
更像是一种按需加载的实现,比如你哪里需要使用Promise
,只要在这个文件头部require Promise from 'babel-runtime/core-js/promise'
就可以。 -
Babel
提供了单独的包babel-runtime
用以提供编译模块的工具函数,启用插件babel-plugin-transform-runtime
后,Babel
就会使用babel-runtime
下的工具函数。
- babel-plugin-transform-runtime
-
transform-runtime
是利用plugin
自动识别并替换代码中的新特性,你不需要再引入,只需要装好babel-runtime
和 配好plugin
就可以了。 -
方便使用
babel-runtime
,解决手动require
的苦恼。它会分析我们的ast
中,是否有引用babel-rumtime
中的垫片(通过映射关系),如果有,就会在当前模块顶部插入我们需要的垫片。 -
按需替换,检测到你需要哪个,就引入哪个
polyfill
,如果只用了一部分,打包完的文件体积对比babel-polyfill
会小很多。而且transform-runtime
不会污染原生的对象,方法,也不会对其他polyfill
产生影响。 -
transform-runtime
的方式更适合开发工具包,库,一方面是体积够小,另一方面是用户(开发者)不会因为引用了我们的工具,包而污染了全局的原生方法,产生副作用,还是应该留给用户自己去选择。 -
同时
transform-runtime
的转换也是非侵入性的,也就是它不会污染你的原有的方法,比如挂在Array
原型上的includes
方法就只能使用babel-polyfill
,使用场景应该是库,遇到需要转换的方法它会另起一个名字,否则会直接影响使用库的业务代码,平常的项目使用babel-polyfill
即可。 -
babel-plugin-transform-runtime
配置选项:- helpers:默认值为
true
,表示是否开启内联的babel helpers
(即babel
或者环境本来存在的某些对象方法函数),如:extends
,etc
这样的在调用模块名字时将被替换名字。 - polyfill:默认值为
true
,表示是否把内置的东西(Promise, Set, Map
)等转换成非全局污染的。 - regenerator:默认值为
true
,是否开启generator
函数转换成使用regenerator
runtime
来避免污染全局域。 - moduleName:默认值为
babel-runtime
,当调用辅助 设置模块(module
)名字/路径。
- helpers:默认值为
babel-polyfill
与babel-runtime
的比较:
-
babel-polyfill
的原理是当运行环境中并没有实现的一些方法,babel-polyfill
会做兼容。babel-runtime
它是将es6
编译成es5
去执行。我们使用es6
的语法来编写,最终会通过babel-runtime
编译成es5
.也就是说,不管浏览器是否支持ES6
,只要是ES6
的语法,它都会进行转码成ES5
,所以就有很多冗余的代码。 -
babel-polyfill
它是通过向全局对象和内置对象的prototype
上添加方法来实现的。比如运行环境中不支持Array.prototype.find
方法,引入polyfill
, 我们就可以使用es6
方法来编写了,但是缺点就是会造成全局空间污染。babel-runtime
它不会污染全局对象和内置对象的原型,比如说我们需要Promise
,我们只需要import Promise from 'babel-runtime/core-js/promise'
即可,这样不仅避免污染全局对象,而且可以减少不必要的代码。babel-plugin-transform-runtime
插件,可以帮助我们去避免手动引入import
的痛苦,并且它还做了公用方法的抽离,polyfill
仅仅存在一份。
babel-polyfill
的安装及使用
babel-polyfill
是全局垫片,为应用准备,通过npm install babel-polyfill –save
命令就可以下载babel-polyfill
- 如果想要直接在所需代码上使用,可以直接引入,代码如下所示:
import 'babel-polyfill'
- 如果想在
webpack
中使用,可以在entry
中添加,也可以在babel
的env
中设置useBuildins
为true
来开启,代码如下所示:
entry: {
app: './app.js',
common: [
`babel-polyfill`,
`whatwg-fetch`,
`react`,
`react-dom`,
`redux`,
`react-redux`,
`js-cookie`,
],
},
babel-runtime
的安装及使用
-
babel-runtime
是局部垫片,为开发框架准备,babel-runtime
作为生产依赖(使用--save
),babel-plugin-transform-runtime
作为开发依赖(使用--save-dev
),通过npm install --save-dev babel-plugin-transform-runtime
命令下载babel-plugin-transform-runtime
,通过npm install --save babel-runtime
命令下载babel-runtime
-
在
.babelrc
文件中使用- 未包含选项,代码如下所示:
{ "plugins": ["transform-runtime"] }
- 包含选项,代码如下所示:
{ "plugins": [ ["transform-runtime", { // 辅助,表示是否开启内联的babel helpers(即babel或者环境本来的存在的垫片或者某些对象方法函数)(clasCallCheck,extends,etc)在调用模块名字(moduleName)时将被替换名字 "helpers": false, // 垫片,表示是否把内置的东西(Promise,Set,Map,tec)转换成非全局污染垫片 "polyfill": false, // 重新生成,是否开启generator函数转换成使用regenerator runtime来避免污染全局域 "regenerator": true, // 模块名字,当调用辅助(内置垫片)设置模块(module)名字/路径 "moduleName": "babel-runtime" }] ] }
三、webpack 打包 Typescript 文件
-
创建一个空文件夹,通过
npm init
命令进行初始化创建package.json
文件,通过npm install webpack typescript ts-loader awesome-typescript-loader --save-dev
命令下载webpack、typescript、ts-loader 和 awesome-typescript-loader
。 -
创建
webpack.config.js
文件,entry
配置入口文件,output
配置出口文件,module
中定义对应的rules
,test
匹配ts
文件,use
使用ts-loader
,代码如下所示:
module.exports = {
entry: {
'app': './src/app.ts'
},
output: {
filename: '[name].bundle.js'
},
module: {
rules: [
{
test: /\.tsx?$/,
use: {
loader: 'ts-loader'
}
}
]
}
}
- 在
tsconfig.json
文件中,compilerOptions
是编译配置选项,include
是包含,exclude
是不包含,代码如下所示:
{
"compilerOptions": {
"module": "commonjs",
"target": "ES5",
"allowJs": true,
"typeRoots": [
"./node_modules/@types"
]
},
"include": ["./src/*"],
"exclude": ["./node_modules/"]
}
- 在
app.ts
文件中,编写ts
代码,代码如下所示:
import * as _ from 'lodash'
console.log(_.chunk([1,2,3,4], 2))
const NUM = 45
interface Cat {
name: String,
gender: String
}
function touchCat (cat: Cat) {
console.log('hello', cat.name)
}
touchCat({
name: 'tom',
gender: 'male'
})
- 通过
webpack --config webpack.conf.js
可以进行打包Typescript
文件。