基本信息:
// webpack在执行时,除在命令行传入参数,还可以通过指定的配置文件来执行。默认会搜索当前目录下webpack.config.js。
// 这个文件是一个node.js模块,返回一个json格式的配置对象,或者通过--config选项来指定配置文件。
var webpack = require('webpack');
module.exports = {
entry:'./entry.js', //入口文件
// entry可以是个字符串或数组或者是对象。
// 当entry是个字符串的时候,用来定义入口文件:
// 当entry是个数组的时候,里面同样包含入口js文件,另外一个参数可以是用来配置webpack提供的一个静态资源服务器
// ,webpack-dev-server。webpack-dev-server会监控项目中每一个文件的变化,实时的进行构建,并且自动刷新页面:
// entry: [
// 'webpack/hot/only-dev-server',
// './js/app.js'
// ]
output:{
//node.js中__dirname变量获取当前模块文件所在目录的完整绝对路径
path:__dirname, //输出位置
filename:'build.js' //输入文件
},
// output参数是个对象,用于定义构建后的文件的输出。其中包含path和filename
module:{ //关于模块的加载相关,我们就定义在module.loaders中。这里通过正则表达式去匹配不同后缀的文件名
// ,然后给它们定义不同的加载器。比如说给less文件定义串联的三个加载器(!用来定义级联关系):
// loaders: [
// { test: /\.js?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
// { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
// { test: /\.css$/, loader: "style!css" },
// { test: /\.less/, loader: 'style-loader!css-loader!less-loader'}
// ]
loaders:[
{
test:/\.css$/, //支持正则
loader:'style-loader!css-loader'
}
]
},
//其他解决方案配置
resolve:{ //webpack在构建包的时候会按目录的进行文件的查找,
// resolve属性中的extensions数组中用于配置程序可以自行补全哪些文件后缀
extensions:['','.js','.json','.css','.scss'] //添加在此的后缀所对应的文件可省略后缀,
// 然后我们想要加载一个js文件时,只要require(‘common’)就可以加载common.js文件了。
},
//插件
plugins:[
new webpack.BannerPlugin('This file is create by baibai')
]
// 当我们想在项目中require一些其他的类库或者API,而又不想让这些类库的源码被构建到运行时文件中,
// 这在实际开发中很有必要。此时我们就可以通过配置externals参数来解决这个问题:
//
// externals: {
// "jquery": "jQuery"
// }
//
//
// 这样我们就可以放心的在项目中使用这些API了:var jQuery = require(“jquery”);
}
例子的webpack.config.js:
var htmlWebpackPlugin=require('html-webpack-plugin');//自动生成html文件
var path=require('path');//path是内置的
var WebpackDevServer = require('webpack-dev-server');//自动刷新模块
//对外暴露一个对象
module.exports={
// entry:__dirname +"/app/index.js",//打包的入口文件 对象或字符串
entry:{//打包多个入口文件
build:__dirname+"/es6/index.js"
},
output:{//配置打包结果 对象
path:__dirname +"/es6_build/",//定义输出文件路径
// filename:"build.js",//指定打包文件名称
filename:"[name].js"//指定多个打包文件名称
},
module:{//对文件的处理逻辑 数组
loaders:[//加载器是数组,数组中的每一项是一个对象
{
test:/.css$/,//是一个正则,处理后缀名为css的文件,匹配到的文件名后缀
// webpack在打包过程中,遇到后缀为css的文件,就会使用style-loader和css-loader去加载这个文件。
loaders:["style-loader","css-loader"],//放加载器,一个是字符串,两个就写成数组
// 最后计算完的css,将会使用style-loader生成一个内容为最终解析完的css代码的style标签,放到head标签里。
// 需要注意的是,loader是有顺序的,webpack肯定是先将所有css模块依赖解析完得到计算结果再创建style标签。
// 因此应该把style-loader放在css-loader的前面(webpack loader的执行顺序是从右到左)。
exclude:"/node_modules"//要排除的文件夹
},
{
test:/.js$/,
loaders: ["babel-loader"], //将es6代码转换为es5代码
exclude:"/node_modules",
include:path.resolve(__dirname,"/es6/")//要包含的文件
}
]
},
devServer:{//配置服务
hot:true, //启用热模块替换
inline:true //自动刷新页面时使用inline模式(将webpack-dev-sever的客户端入口添加到包(bundle)中)
//此模式支持热模块替换:热模块替换的好处是只替换更新的部分,而不是页面重载.
},
resolve:{
extensions:[' ','.js','.css','.jsx'] //自动补全识别后缀名
},
plugins:[
// 插件可以完成更多loader不能完成的功能。插件的使用一般是在webpack.config.js中的plugins 选项中指定。
// Webpack本身内置了一些常用的插件,还可以通过npm安装第三方插件。
new htmlWebpackPlugin({//自动生成html文件
title:"欢迎",//title标签为欢迎这个字符串
chunks:["build"] //引用的模块(abc.js)
}),
new webpack.HotModuleReplacementPlugin() //启用热模块替换
]
}
babel原理:
babel是一个转译器,感觉相对于编译器compiler,叫转译器transpiler更准确,因为它只是把同种语言的高版本规则翻译成低版本规则,而不像编译器那样,输出的是另一种更低级的语言代码。
但是和编译器类似,babel的转译过程也分为三个阶段:parsing(解析)、transforming(转换)、generating(产生),以ES6代码转译为ES5代码为例,babel转译的具体过程如下:
ES6代码输入 ==》 babylon进行解析 ==》 得到AST
==》 plugin用babel-traverse对AST树进行遍历转译 ==》 得到新的AST树
==》 用babel-generator通过AST树生成ES5代码
此外,还要注意很重要的一点就是,babel只是转译新标准引入的语法,比如ES6的箭头函数转译成ES5的函数;而新标准引入的新的原生对象,部分原生对象新增的原型方法,新增的API等(如Proxy、Set等),这些babel是不会转译的。需要用户自行引入polyfill来解决。
babel会从当前转译的文件所在目录下查找配置文件,如果没有找到,就顺着文档目录树一层层往上查找,一直到.babelrc文件存在或者带babel字段的package.json文件存在为止。
.babelrc文件:
{"presets":["es2015"]} //presets是官方预设的插件集,es2015是其中一个
热加载:
模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:
- 保留在完全重新加载页面时丢失的应用程序状态。
- 只更新变更内容,以节省宝贵的开发时间。
- 调整样式更加快速 - 几乎相当于在浏览器调试器中更改样式。
在开发过程中,可以将 HMR 作为 LiveReload 的替代。webpack-dev-server 支持 hot
模式,在试图重新加载整个页面之前,热模式会尝试使用 HMR 来更新。
实现原理:
在应用程序中:
通过以下步骤,可以做到在应用程序中置换(swap in and out)模块:
- 应用程序代码要求 HMR runtime 检查更新。
- HMR runtime(异步)下载更新,然后通知应用程序代码。
- 应用程序代码要求 HMR runtime 应用更新。
- HMR runtime(异步)应用更新。
你可以设置 HMR,以使此进程自动触发更新,或者你可以选择要求在用户交互时进行更新。
在编译器中:
除了普通资源,编译器(compiler)需要发出 "update",以允许更新之前的版本到新的版本。"update" 由两部分组成:
- 更新后的 manifest(JSON)
- 一个或多个更新后的 chunk (JavaScript)
manifest 包括新的编译 hash 和所有的待更新 chunk 目录。每个更新 chunk 都含有对应于此 chunk 的全部更新模块(或一个 flag 用于表明此模块要被移除)的代码。
编译器确保模块 ID 和 chunk ID 在这些构建之间保持一致。通常将这些 ID 存储在内存中(例如,使用 webpack-dev-server 时),但是也可能将它们存储在一个 JSON 文件中。
在模块中:
HMR 是可选功能,只会影响包含 HMR 代码的模块。举个例子,通过 style-loader
为 style 样式追加补丁。 为了运行追加补丁,style-loader
实现了 HMR 接口;当它通过 HMR 接收到更新,它会使用新的样式替换旧的样式。
类似的,当在一个模块中实现了 HMR 接口,你可以描述出当模块被更新后发生了什么。然而在多数情况下,不需要强制在每个模块中写入 HMR 代码。如果一个模块没有 HMR 处理函数,更新就会冒泡。这意味着一个简单的处理函数能够对整个模块树(complete module tree)进行更新。如果在这个模块树中,一个单独的模块被更新,那么整组依赖模块都会被重新加载。