webpack 总结 - archering/basic GitHub Wiki
webpack核心功能:
- 模块划分
- 按照模块的依赖顺序将多个module合并成一个bundle文件,在浏览器上运行。
webpack支持目前已知的三种主要module系统
- commonJS
- AMD
- ES6(ES2015,import,export)
要使用webpack 必须先安装webpack
npm install webpack@2.* --save-dev
webpack的运行依赖一个webpack.config.js的配置文件。
这个配置文件基本结构和关键点是:
var config = {
entry:"./src/index.js",//入口文件地址 (相对路径,相对webpack.config.js)
output:{
path:path.resolve(__dirname,"dist"), //(绝对路径) 合并文件bundle.js 地址
filename:"bundle.js"//合并输出文件的名字
}
}
运行webpck 有两种方式
(1)如果你是全局安装的 webpack
npm install -g webpack
那么你可以直接在命令行输入 webpack
来运行程序
(2)如果你是本地安装的webpack 需要在package.json 里面配置
scripts:{
"build":"webpack"
}
//然后在命令行输入
npm run build //来运行webpack程序
babel 是一个node编译库(Babel is a JavaScript compiler),用来将ES6,ES7 转成目前浏览器支持的ES5
webpack 是一个node程序 用js写成,作用是将多个划分好的模块(js文件)合并成一个bundle
先解释下webpack是啥
webpack仅仅能明白和理解纯javascript,要想使webpack能处理其他语言或者不同版本的语言,比如css(css-loader),typscript(ts-loader),ES2016 ... 就需要一个预处理程序读取这些文件并将它们转成webpack能理解的东西。 webpack在它的配置文件中添加了一个module 属性,用于支持这种特性,当然可以支持多个。webpack文档专门有一节说明这个和用法。
module.rules allows you to specify several loaders within your webpack configuration
module 是webpack生成bundle之前预处理源程序的地方
例如下面webpack为了能够处理ES6的东西,就需要借助babel
如何使用babel,先要知道三个物件
babel-loader : Teach babel how to work with webpack
babel-core : Knows how to take in code,parse it, and generate some output code (输入输出机制)
babel-preset-env: 根据具体的语法规则将ES6/7/8转成 ES5, (BABEL的本职工作)
webpack 可以同时支持在一个项目里面使用多个module system
webpack module(loader)
module:{
rules:[
{
use:"babel-loader",
test:/\.js$/
},
{
use:["style-loader","css-loader"], //从右往左执行,先依赖css-loader处理,再依赖style-loader处理
test:/\.css$/
}
]
}
ES6 中import 有两种: 一种是引入并引用,需要module 显示的export default divi
import divi from "./divide"
另一种是引入并执行,不引用这里面的对象
import "./image_viewer";//引入并执行相关代码
plugins
webpack 提供的这个功能,Plugins range from bundle optimization and minification all the way to defining environment-like variables. (webpack的基本功能是将多个文件按照依赖加载顺序合并,plugins则提供了额外的功能,比如文件压缩,代码优化,分离文件,注释删除,变量替换等....)
对应的在webpack.config.js 提供了相应的plugins选项, (1)首先你需要npm install 安装这个插件,(2)然后在webpack.config.js 引入require这个插件,最后在plugins选项中列出这个插件的实例。
const webpack = require('webpack'); //to access built-in plugins
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
按需加载相应的js文件
首先说明一个属性publicPath
var config = {
entry:"./src/index.js",//入口文件地址 (相对路径,相对webpack.config.js)
output:{
path:path.resolve(__dirname,"dist"), //(绝对路径) 合并文件bundle.js 地址
filename:"bundle.js",//合并输出文件的名字
publicPath:"./dist/" // 这个变量对于打包合并后的文件分开存放,split 文件很有用,知道去哪里放这些文件
}
}
story: (1)首先页面一加载,显示在页面上的是一个按钮(此时页面上只加载了一个bundle.js)。 (2)用户点击按钮后加载另一个文件(0.bundle.js),并在页面上渲染一副图片。
image_viewer_split.js
let button = document.createElement("button");
button.innerHTML = "click me to show image";
button.onclick = () => { //点击之后加载一个新的js
//System.import 回去服务端请求新的资源,返回一个promise, 这个方法类似fetch
System.import("./image_viewer_itself").then((module) =>{
module.default();
});
}
document.body.appendChild(button);
image_viewer_itself.js
import "./css/image_viewer.css";// 1非js文件的import 都要加扩展名。 2 如果只是引入并执行文件,而不需要引用文件内容,可以只写引入地址
//programmatic API 如果想基于某些条件或等某个事件发生后再加载需要的模块
//System.import方法
export default () => {
var img = document.createElement("img");
img.src = "http://lorempixel.com/200/200/";// 这是一个线上服务,可以获得随机的照片
document.body.appendChild(img);
}
这种情况下打包,就会在dist 下面出现两个包,一个是bundle.js 一个是 0.bundle.js 如果你在开发中有多个分段加载的js 则会生成0.bundle.js 1.bundle.js ....
story: 随着项目越写越大,引入的第三方框架约来越多, 利用webpack 打包输出一个bundle坑定不行。 我们最基本的需求,比如把自己写的js文件打包成一个bundle,第三方库合并成一个bundle 已经是最近本的需求了。 这个就需要改变两个东西,(1)修改webpack.config.js (2) 引入插件,分割bundle。
改变的第一个地方
var config = {
entry:{
bundle:"./src/js/index.js",
vendor:['react','faker','redux'] //这里面是package.json 里面的所有dependencies 里面module
},
output:{
path:path.resolve(__dirname,"dist"),
filename:"[name].js" //这里面变量[name] 就会从 entry 里面去取 key (bundle, vendor)生成相应的bundle.js vendor.js文件
}
上面这种写法的结果会出现,打了两个bundle, bundle.js 和 vendor.js 但是bundle.js 里面还是包含了vendor.js 类似这个:
bundle.js 3.37 MB 0 [emitted] [big] bundle
vendor.js 3.14 MB 1 [emitted] [big] vendor
我们期望的是 把bundle.js里面包含的verdor部分删除,这就需要借助一个插件
plugins:[
new webpack.optimize.CommonsChunkPlugin({ //这个不需要require webpack自带的
name:'vendor' //要剔除的部分 和 entry 里面对应的key
})
]
结果如下,bundle.js变小了
bundle.js 228 kB 0 [emitted] bundle
vendor.js 3.14 MB 1 [emitted] [big] vendor