webpack工做原理:css
经过一个入口文件,main.js开始找到你的项目的全部依赖文件,使用loaders处理它们,最后打包为一个浏览器可识别的JavaScript文件。html
正如js文件能够是一个“模块(module)”同样,其余的(如css、image或html)文件也可视做模 块。所以,你能够require('myJSfile.js')亦能够require('myCSSfile.css')。这意味着咱们能够将事物(业务)分割成更小的易于管理的片断,从而达到重复利用等的目的。前端
传统的模块打包工具(module bundlers)最终将全部的模块编译生成一个庞大的bundle.js文件。可是在真实的app里边,“bundle.js”文件可能有10M到15M之大可能会致使应用一直处于加载中状态。所以Webpack使用许多特性来分割代码而后生成多个“bundle”文件,并且异步加载部分代码以实现按需加载。vue
最开始以前先说下:node
一、package.json文件。 这个文件是npm的说明文件,建立方式是npm init,有了package.json文件之后就能够局部安装webpack模块做为依赖包了。(安装方式略)react
package.json文件中的scripts中是一个对象,里面是{keyName : value}的方式,在node的环境下:npm run keyName 就能执行 value中的配置,因此这里能够把webpack的配置放到这里。webpack
package.json中的脚本部分已经默认在命令前添加了node_modules/.bin
路径,因此不管是全局仍是局部安装的Webpack,你都不须要写前面那指明详细的路径了web
二、webpack.config.js文件 一般放在项目的根目录中,它自己也是一个标准的Commonjs规范的模块,具体的配置项经过module.exports = {}暴露出去, vue-router
module.exports = { entry : " ", /*入口输入项*/ output : {}, /*输出项*/ module : {/*加载器配置*/ loaders : [ { test: / /, loader: ' ' } /*test是正则匹配的文件类型,loader是使用的加载资源loader*/ ] }, plugins : {},/*插件项*/ resolve : { /*其它解决方案配置*/ extensions : [],/*require的文件扩展名*/ alias : {},/*别名,用来缩写*/ root : "",/*查找module的绝对根路径*/ }, externals : {}/*项目中额外的类库或API*/ }
各个区域的备注:typescript
一、var webpack = require('webpack');
// 不需解释,引入webpack,之后能够调用webpack的一些方法(需在devDependencies下安装webpack)。
二、var path = require('path');
// 这是node下面的Path模块(需在devDependencies下安装path),用于处理文件路径,由于js是前端脚本,不多去处理文件路径的问题,这个在后端语言中很常见(需掌握)。
******path下面有4个经常使用的方法******
path.join('参数1' ,'参数2') :用路径分隔符链接,它会自动识别系统,Unix系统是”/“,Windows系统是”\“。 path.join(mydir, "foo"); unix下----> 返回路径mydir/foo
path.resolve():最终结果,取出绝对路径。它能够接受多个参数,依次表示所要进入的路径,直到将最后一个参数(至关于cd进入每个参数,最后调用cwd命令)
例子1: path.resolve('foo/bar', '/tmp/file/', '..', 'a/../subfile')
$ cd foo/bar $ cd /tmp/file/ $ cd .. $ cd a/../subfile $ pwd(显示当前目录)
例子2:path.resolve('/foo/bar', './baz') // '/foo/bar/baz'
例子3:path.resolve('/foo/bar', '/tmp/file/') // '/tmp/file'
例子4:path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif')// 若是当前目录是/home/myself/node,返回// /home/myself/node/wwwroot/static_files/gif/image.gif
结论:是 / 开头的绝对路径那么就替换成最新的 是 ./ 开头的相对路径就后面添加 是 ../ 开头的回退路径,就取消一层,最后输出所在的全路径名
path.relative() path.parse()略
三、process进程对象及其属性
process对象是Node的一个全局对象,能够在任意位置使用,没必要经过require
命令加载。
process对象提供一系列属性 process.cwd() process.env _ _dirname
process.cwd()
与__dirname
的区别:前者进程发起时的位置的绝对路径(在node中表明所输命令行上面的那一行,
后者是脚本的位置(文件原本来本处于的目录位置),二者多是不一致的。
process.env:process.env
属性返回一个对象,包含了当前Shell的全部环境变量,
通常这里的作法,新建一个环境变量NODE_ENV,用它肯定当前所处的开发阶段。
生产阶段设为production
,开发阶段设为development。
用法:A 脚本中读取
process.env.NODE_ENV来肯定是哪一个阶段。B 运行脚本时,设置环境变量 node命令行中:
$ NODE_ENV=production node app.js
var env = process.env.NODE_ENV env === 'development' env === 'production'
四、webpack-dev-server依赖 支持2种自动刷新的方式 ——iframe模式和inline模式,默认监听8080端口
webpack-dev-server是一个Node.js服务器,一个小型的静态文件服务器(须要开发者从npm自行安装),为经过webpack打包生成的资源文件提供Web服务。
iframe模式:在网页中嵌入一个iframe
,将咱们本身的应用注入到这个 iframe
当中去,所以每次你修改的文件后,都是这个 iframe
进行了 reload。
访问路径:
localhost:8080/webpack-dev-server/index.html。 ---------- 不推荐使用
inline模式:是 webpack-dev-server
会在你的 webpack.config.js
的入口配置文件中再添加一个入口
访问的路径是:localhost:8080/index.html ---------- 推荐使用
inline模式又分两种启动命令的方式:(Node.js API命令行方式和CLI模式(cmd line)):
一、CLI模式(又分两种写法):
写法a:在node窗口环境下输入,webpack须要全局安装,若是只是局部安装的话 node_modules/.bin/webpack
写法b:在package.json文件中的script中配置,用npm run来运行webpack命令
写法 1: // 全局安装 npm install webpack-dev-server --save // 运行 $ webpack-dev-server --inline --hot
写法 2: // 添加到package.json scripts "scripts": { "start": "webpack-dev-server --inline --hot", ... } // 运行: $ npm start
其中 --hot --inline为webpack-dev-server参数,有两种方式传参:
// 经过CLI传参 webpack-dev-server --hot --inline// 经过webpack.config.js文件的"devServer"对象 devServer: { inline: true, hot:true }
webpack-dev-server的一些经常使用选项(用于开发dev时候,pro时候不用),能够写成 --形式,也能够在devServer对象中以key:value(boolean)形式来配置
// 当资源发生改变,如下三种方式都会生成新的bundle,可是又有区别: // 1. 不会刷新浏览器 $ webpack-dev-server //2. --inline“热加载”功能,刷新浏览器 $ webpack-dev-server --inline
//3. --hot “热替换,尝试从新加载组件改变的部分(而不是从新加载整个页面) // --inline --hot 当资源改变时,webpack-dev-server将会先尝试HRM(即热替换),若是失败则从新加载整个入口页面 $ webpack-dev-server --inline --hot --color // 打包信息带有颜色显示 --no-colors // 关闭颜色 --quiet // 控制台中不输出打包的信息 --compress // 开启gzip压缩 --progress // 显示打包过程当中的进度 --host // 配置主机名或IP, 0.0.0.0绑定到全部主机 --port // 配置端口号 --history-api-fallback // 是否支持HTML5历史API撤退,若是是true,则每次跳转都指向index.html
二、Node.js API命令行方式:
五、module.exports = { 配置项 } 配置项解析:
entry选项: webpack做用的入口文件,也就是启动webpack时候要最早处理的文件,通常这个文件内部会引用不少其余所依赖的模块。
此文件内部的写法也能够用import引入其余须要的模块,好比 import Vue from 'vue'; import VueRouter from 'vue-router';。
能够是字符串、数组或对象,
路径:相对webpack.config.js的路径,好比:此处的"./entry.js" 好比"./src/index.js"
路径也能够用path模块下的方法来配置:entry: path.resolve(__dirname, './src/app.js'),path.resolve()方法,能够结合咱们给定的两个参数最后生成绝对路径,最终指向的就是咱们
的app.js文件,此法要引入path模块,var path = require('path');
字符串:单一入口用字符串,不过单一入口用数组和对象也是能够的,无所谓
数组:单页面的多入口,且彼此不互相依赖的文件,使用数组格式
对象:多页面的多入口,有多个html文件,多处引用。如下的配置将会生成两个js文件:indexEntry.js和profileEntry.js分别会在index.html和profile.html中被引用。。
对象的混合使用:
output选项:
output输出文件,最终提交出去的通过合并压缩等等一系列操做的输出文件。
参数是个对象,定义了输出文件的位置path及名字filename和 publishPath 属性或者chunkFilename
path ---- 打包文件存放的绝对路径, 若是文件目录不存在那么自动建立
filename ---- 打包后的文件名,(以下例子)
publishPath ---- 表明静态资源发布后的前缀地址,即 网站运行时的访问路径(主要用于生产环境静态资源的从新配置),被许多Webpack的插件用于在生产模式下更新内嵌到css、html文件里的url值。
chunkFilename ---- 用来打包require.ensure方法中引入的模块,若是该方法中没有引入任何模块则不会生成任何chunk块文件
注意:对于不是在require.ensure方法中引入的模块,此属性不会生效,只能用CommonsChunkPlugin插件来提取
filename :当咱们在entry中定义构建多个文件("./entry1", "./entry2")时,filename能够对应的更改成[name].js,用于定义不一样文件构建后的名字。
举例:输入 page2: ["./entry1", "./entry2"],输出filename: "[name].bundle.js"
publishPath :在localhost(本地开发模式)里的css文件中边你可能用“./test.png”这样的url来加载图片,可是在生产模式下“test.png”文件可能会定位到CDN上而且你的Node.js服务器多是运行在云平台上边的。这就意味着在生产环境你必须手动更新全部文件里的url为CDN的路径,有了这个选项配置,就简单多了。
下图是利用publishPath和url-loader在生产模式编译输出时候更改了url的路径(相对---->绝对)
// 开发环境:Server和图片都是在localhost(域名)下 .image { background-image: url('./test.png'); } // 生产环境:Server部署下HeroKu可是图片在CDN上 .image { background-image: url('https://someCDN/test.png'); }
一些output的配置项。
module选项:
loaders : [{},{},{}] 对象组成的数组
module: { loaders: [{ test: /\.js$/, // 匹配.js文件,若是经过则使用下面的loader (必选) loader: 'babel' // 使用babel(babel-loader的简写)做为loader }] (必选) exclude: /node_modules/, // 排除node_modules文件夹 ,不须要处理 (可选) include: /node_modules/, // 手动添加必须处理的文件夹 (可选) query: {} // 为loader提供额外的配置选项 (可选) }] }
test选项:
loader选项:将浏览器不能识别的类型,经过相应的loader模块加载器转换成可识别的代码。
规则:链式(管道式)的加载器(从右往左执行),须要多个loader的时候,从右往左执行,且不一样的loader之间应该用!来分割开。
可简写,省略-loader字段,style-loader!css-loader能够写成style!css
举例:css-loader 处理css文件以及css的依赖(@import移入的css文件) style-loader 添加style标签嵌入到html中。
因此顺序就是:
query:loader自身配置项(好比:针对图片的url配置)
配置url-loader来将小于1024字节的图片使用DataUrl替换而 大于1024字节的图片使用url,咱们能够用以下两种方式经过传入“limit“参数来实现这一目的:
两种方式:(用参数模式或者query模式)
/*使用?参数的方式*/ { test :/\.png$/, loader: 'url-loader?limit=1024' } /*使用query属性*/ { test :/\.png$/, loader: 'url-loader' query:{
limit:1024
name: utils.assetsPath('img/[name].[hash:7].[ext]')
} }
特殊的:
一、babel-loader的query配置项,他能够写到 loader[{}]中,也能够单出提出来写到一个 .babelrc文件中,webpack编译的时候会自动查找。
安装:babel-core babel-loader babel-preset-es2015
module: { loaders: [ { test: /\.jsx?$/, exclude: /(node_modulesbower_components)/, loader: 'babel', query: { // 直接写到loader内部 presets: ['react', 'es2015'] } } ] }
或者
//webpack.config.js 文件 无query配置项 module: { loaders: [ { test: /\.jsx?$/, exclude: /(node_modulesbower_components)/, loader: 'babel' } ] }
//.bablerc文件 { presets: ['react', 'es2015'] }
.bablere文件的其余配置项解析
// .bablere文件的其余配置项解析 { "presets": ["es2015", "stage-2"], // XXXXXXXXXXXXXXXXXXX "plugins": ["transform-runtime"], // XXXXXXXXXXXXXX "comments": false // XXXXXXXXXXXXXXXXXXX }
二、PostCSS 安装postcss-loader 和 autoprefixer(自动添加前缀的插件)
直接写在module:{}中,而不是loader:[{}]中,和loader同级的。
postcss: [module: { loaders: [ { test: /\.json$/, loader: "json" }, { test: /\.js$/, exclude: /node_modules/, loader: 'babel' }, { test: /\.css$/, loader: 'style!css?modules!postcss' } ] },
require('autoprefixer')//调用autoprefixer插件 ],
devserver服务选项(对象):能够参考上面的
devServer: { contentBase: "./public",//默认webpack-dev-server会为根文件夹提供本地服务器,若是想为另一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到“public"目录) colors: true,//终端中输出结果为彩色 port : 8888,// 设置默认监听端口,若是省略,默认为”8080“ historyApiFallback: true,// 在开发单页应用时很是有用,它依赖于HTML5 history API,若是设置为true,全部的跳转将指向index.html inline: true// 当源文件改变时会自动刷新页面 }
devtool开发调试选项:
打包后的文件有时候你是不容易找到出错了的地方对应的源代码的位置的,Webpack在打包时能够为咱们生成的source maps,这为咱们提供了一种对应编译文件和源文件的方法。
//配置生成Source Maps,选择合适的选项 // 在一个单独的文件中产生一个完整且功能彻底的文件,减慢打包文件的构建速度 devtool: 'source-map', // 在一个单独的文件中生成一个不带列映射的map,提升项目构建速度,可是只能对应到具体的行,不能对应到具体的列(符号) devtool: 'cheap-module-source-map', // 使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项能够在不影响构建速度的前提下生成完整的sourcemap,可是对打包后输出的JS文件的执行具备性能和安全的隐患。不过在开发阶段这是一个很是好的选项,可是在生产阶段必定不要用这个选项; devtool: 'eval-source-map', // 这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射 (中小项目用) devtool: 'cheap-module-eval-source-map',
plugins插件选项(数组):用new XX()的形式。。
plugins: [ new HtmlWebpackPlugin({ template: __dirname + "/app/index.tmpl.html" // 命名模板文件名称为app下的index.tmpl.html,他到时候会自动被添加自动添加所依赖的 css, js,favicon等文件 }), new webpack.optimize.OccurenceOrderPlugin(), new webpack.optimize.UglifyJsPlugin(), new ExtractTextPlugin("[name]-[hash].css") ]
HtmlWebpackPlugin // 这个插件的做用是依据一个简单的模板,帮你生成最终的Html5文件,这个文件中自动引用了你打包后的JS文件。每次编译都在文件名中插入一个不一样的哈希值。
resolve选项(对象):
externals
webpack的一些插件:
WebPack.optimize.UglifyJsPlugin (WebPack内建插件)// 代码压缩
WebPack.optimize.CommonsChunkPlugin(WebPack内建插件)//提取公用文件,合并到一块儿
var HtmlWebpackPlugin = require('html-webpack-plugin'); //自动生成带hash的HTML 文件
var ExtractTextPlugin = require("extract-text-webpack-plugin"); // 独立样式文件,会将全部的样式文件打包成一个单独的style.css
参考:http://www.jianshu.com/p/dcb28b582318