webpack这个工具很是强大。对前端中全部模块进行打包,输出js文件,后续引入这个js文件,在服务器上线,而后在域名中访问写好的项目;webpack还能支持模块化加载(相似python,import xxx from 'ooo')。中文官网连接地址:https://www.webpackjs.com/javascript
现今的不少网页其实能够看作是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,前端社区涌现出了不少好的实践方法。css
这些改进确实大大提升了开发效率,可是利用它们开发的文件每每须要进行额外的处理才能让浏览器识别,手动处理很是繁琐,WebPack类的工具的出现就是为了解决这样的需求。html
webpack 是一个现代 JavaScript 应用程序的 静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个 依赖关系图(dependency graph),其中包含应用程序须要的每一个模块,而后将全部这些模块打包成一个或多个 bundle。前端
WebPack能够看作是模块打包机:它作的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。vue
Webpack和另外两个并无太多的可比性,Gulp/Grunt是一种可以优化前端的开发流程的工具,而WebPack是一种模块化的解决方案,不过Webpack的优势使得Webpack在不少场景下能够替代Gulp/Grunt类的工具。java
Grunt和Gulp的工做方式是:在一个配置文件中,指明对某些文件进行相似编译,组合,压缩等任务的具体步骤,工具以后能够自动替你完成这些任务。node
Webpack的工做方式:把你的项目当作一个总体,经过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的全部依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。python
若是要将两者进行比较,Webpack的处理速度更快更直接,能打包更多不一样类型的文件。jquery
这个是解析咱们es6的代码的,为何要用它呢,由于对于一些ie浏览器,甚至FF浏览器,低版本的还不能识别咱们的es6代码,那么vue里面好多还让咱们去写es6的代码,这个时候咱们就能够用babel这个工具将咱们的es6的代码转译成浏览器能识别的代码.webpack
左边是咱们写的es6代码,右边是经过babel这个工具编译以后的代码。这个代码能在咱们各个浏览器中去识别。
因此babel是用于编写下一代JavaScript的编译器。
在前端中一个js文件就是一个模块,在js中没有模块化的概念。
webpack:对前端中的资源编译打包、支持模块化es6的Model。
在webpack中,全部类型的文件均可以是模块,包括Javascript、CSS、图片、JSON。经过加载器(Loader)将JavaScript 的模块推广到其余类型文件。
(1)2009年初,commonjs规范还未出来,此时前端开发人员编写的代码都是非模块化的,
那个时候开发人员常常须要十分留意文件加载顺序所带来的依赖问题
(2)与此同时 nodejs 开启了js全栈大门,而 requirejs 在国外也带动着前端逐步实现模块化
同时国内 seajs(海纳百川 有容乃大)也进行了大力推广
AMD 规范 ,具体实现是:requirejs define('模块id',[模块依赖1,模块依赖2],function(){ return ;}) , ajax请求文件并加载
Commonjs || CMD 规范seajs 淘宝玉伯
commonjs和cmd很是类似的
cmd require/module.exports
commonjs是js在后端语言的规范: 模块、文件操做、操做系统底层
CMD 仅仅是模块定义
UMD 通用模块定义,一种既能兼容amd也能兼容commonjs 也能兼容浏览器环境运行的万能代码
(3)npm/bower集中包管理的方式备受青睐,12年browserify/webpack诞生
npm 是能够下载先后端的js代码475000个包
bower 只能下载前端的js代码,bower 在下载bootstrap的时候会自动的下载jquery
browserify 解决让require能够运行在浏览器,分析require的关系,组装代码
webpack 打包工具,占市场主流
(4)es6的module
export default {} || fn || msg,前端中也是有模块的,导入方式是下面这种用法。
import xxx from './index.js'
es6Module 支持import(导入)和export(导出)。跟python的import很像。但它必须在服务器环境下才支持,或者咱们可能经过webpack的babel-loader将es6支持转化成es6的语言。
# 下载webpack,-g表明全局 $ npm i webpack@3.12.0 -g # 查看webpack $ webpack -v 3.12.0
在webpack-demo 目录中新建index.html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模块的基本使用</title> </head> <body> <!--<script type="text/javascript" src="App.js"></script>--> <!--<script type="text/javascript" src="main.js"></script>--> <script type="text/javascript" src="bundle.js"></script> </body> </html>
建立App.js文件:
// es6 module export抛出 import导入 let obj = { name: 'alex' }; export default obj; let age = 23; export {age}; // 做为一个key抛出 export var fav = "鸡汤"; export function add() { console.log('弹出了') }
建立main.js文件:
import app from './App.js' console.log(app); import {age, fav, add} from './App.js' console.log(age); console.log(fav); add();
使用webpack将main.js 打包成 bundle.js文件:
$ webpack ./main.js ./bundle.js Hash: 9f8da91e23bd4d667df5 Version: webpack 3.12.0 Time: 96ms Asset Size Chunks Chunk Names bundle.js 3.54 kB 0 [emitted] main [0] ./App.js 186 bytes {0} [built] [1] ./main.js 128 bytes {0} [built]
查看浏览器conosle输出:
将main.js的内容作以下简写:
import * as o from './App.js' console.log(o);
再次将index.js进行打包:
$ webpack ./main.js ./bundle.js
查看页面输出,做为整个对象抛出,以下所示:
建立index.html内容以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模块的基本使用</title> </head> <body> <div id="app"></div> <script type="text/javascript" src="bundle.js"></script> </body> </html>
建立App.js内容以下:
// es6 module export抛出 import导入 let App = { template: ` <div> 我是一个App组件 </div> ` }; export default App; let age = 23; export {age}; // 做为一个key抛出 export var fav = "鸡汤"; export function add() { console.log('弹出了') }
建立main.js内容以下,引入vue.js文件:
import * as o from './App.js' console.log(o); import Vue from './vue.js' // 引入Vue模块 new Vue({ el: '#app', data(){ return { } }, template:` <App/> `, components: { App:o.default } })
执行webpack,将main.js 打包成 bundle.js文件:
$ webpack ./main.js ./bundle.js Hash: b8b29cf57e405a8f2ee4 Version: webpack 3.12.0 Time: 645ms Asset Size Chunks Chunk Names bundle.js 309 kB 0 [emitted] [big] main [0] (webpack)/buildin/global.js 509 bytes {0} [built] [1] ./main.js 396 bytes {0} [built] [2] ./App.js 257 bytes {0} [built] [3] ./vue.js 289 kB {0} [built]
显示效果以下所示:
webpack.config.js这个配置文件文件名是webpack默认的配置文件文件名。
首先进入项目目录webpack_demo(最近父目录不能是中文)并完成初始化项目:
$ npm init --yes
项目初始化完成后,目录中多出package.json文件,内容以下所示:
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
在webpack_demo项目根目录中安装 webpack:
$ npm i webpack@3.12.0 -D
上例中指定了 webpack 版本号,若是下载时没有指定,安装完成后能够看到当前安装的webpack版本号。
因为配置插件越多命令行会越长(webpack ./main.js ./bundle.js),此时,能够将命令行参数移入webpack配置文件。
新建一个 webpack.config.js 文件:
module.exports = { // entry入口 entry: { main: './main.js' }, // output出口 output: { filename: './bundle.js' } }
index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模块的基本使用</title> </head> <body> <div id="app"></div> <!--<script type="text/javascript" src="App.js"></script>--> <!--<script type="text/javascript" src="main.js"></script>--> <script type="text/javascript" src="bundle.js"></script> </body> </html>
javascript文件:
// App.js let App = { template: ` <div> 我是一个App组件 </div> ` }; export default App; let age = 23; export {age}; // 做为一个key抛出 export var fav = "鸡汤"; export function add() { console.log('弹出了') } // main.js import * as o from './App.js' console.log(o); import Vue from './vue.js' // 引入Vue模块 new Vue({ el: '#app', data(){ return { } }, template:` <App/> `, components: { App:o.default } })
$ webpack
执行打包后,查看页面显示效果:
因为在平常使用中,经常分有开发环境和生成环境。在生产环境下但愿配置有watch,可以去自动编译。但在开发环境下,则不须要有watch,打包完成后退出便可。
在这里复制两份webpack.config.js文件分别命名为:webpack.dev.config.js、webpack.prod.config.js。
而后须要配置package.json文件,让它可以识别这两个新的js文件:
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack --config ./webpack.dev.config.js", "build": "webpack --config ./webpack.prod.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^3.12.0" } }
执行npm run dev/build 来分别给生产环境和开发环境打包:
$ npm run dev $ npm run build
在上面的webpack_demo项目中没有添加css样式。若是要添加css样式,一个是能够直接写在标签的 style 属性中。
再就是能够写在css文件中,在目录中新增main.css文件:
body{ background-color: red; }
而后在main.js中引入应用:
import * as o from './App.js' import Vue from './vue.js' // 引入Vue模块 // 导入css import './main.css' new Vue({ el: '#app', data(){ return { } }, template:` <App/> `, components: { App:o.default } })
此时执行npm run dev,就会发现报错以下所示:
Version: webpack 3.12.0 Time: 670ms Asset Size Chunks Chunk Names ./bundle.js 309 kB 0 [emitted] [big] main [0] (webpack)/buildin/global.js 509 bytes {0} [built] [1] ./main.js 409 bytes {0} [built] [2] ./App.js 257 bytes {0} [built] [3] ./vue.js 289 kB {0} [built] [7] ./main.css 169 bytes {0} [built] [failed] [1 error] + 3 hidden modules ERROR in ./main.css Module parse failed: Unexpected token (1:4) You may need an appropriate loader to handle this file type. | body{ | background-color: red; | } @ ./main.js 12:0-19
style
标签须要注意的是:若是只使用了 css-loader,则 webpack 只是将CSS文件预处理成模块而后打包到构建文件中,并不会插入到页面(这是 style-loader 的做用)。
$ npm install css-loader -D;
$ npm install style-loader -D
下载完成后,能够看到package.json中多了这两个组件:
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack --config ./webpack.dev.config.js", "build": "webpack --config ./webpack.prod.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^2.1.1", "style-loader": "^0.23.1", "webpack": "^3.12.0" } }
修改配置让webpack识别这两个loader :
module.exports = { // entry入口 entry: { main: './main.js' }, // output出口 output: { filename: './bundle.js' }, watch:true, // 模块中的loader,loader加载器能对css、json、png、jpg、mp三、mp四、es6的js代码解析 module:{ loaders:[ { test:/\.css$/, // css结尾的 loader:'style-loader!css-loader' // 依次识别 } ] } }
须要注意的是,loader的顺序很是重要,加载器的执行顺序是从后往前的,若是把 sytle-loader 放在 css-loader 后面,style-loader 是没法理解CSS文件的,须要先通过 css-loader 预处理。
在完成项目开发后,将输出文件打包:
$ npm run dev > webpack_demo@1.0.0 dev /Users/.../webpack_demo > webpack --config ./webpack.dev.config.js Hash: 45b4436bff4c76fd3bc8 Version: webpack 3.12.0 Time: 1142ms Asset Size Chunks Chunk Names ./bundle.js 326 kB 0 [emitted] [big] main [0] (webpack)/buildin/global.js 509 bytes {0} [built] [1] ./main.js 409 bytes {0} [built] [2] ./App.js 257 bytes {0} [built] [3] ./vue.js 289 kB {0} [built] [7] ./main.css 1.07 kB {0} [built] [8] ./node_modules/css-loader/dist/cjs.js!./main.css 1
显示效果:
该插件将为您生成一个HTML5文件,其中包含使用script
标记在正文中的全部webpack包。
(1)该插件主要有两个主要做用:
(2)插件生成html文件的原理:
将 webpack中 entry 配置的相关入口 chunk 和 extract-text-webpack-plugin 抽取的css样式 插入到该插件提供的 template 或者 templateContent 配置项指定的内容基础上生成一个html文件,具体插入方式是将样式 link 插入到 head 元素中,script 插入到 head 或者 body 中。
建立src目录后,建立编辑以下文件:
App.js文件:
// es6 module export抛出 import导入 var App = { template: `<div>{{msg}}</div>`, data(){ return { msg: "咱们学习module 哈哈哈哈 更改了数据" } } }; // 先抛出 export default App;
main.js文件:
import Vue from './vue.js' // 引入Vue模块 import App from './App.js' // 导入css import './main.css' new Vue({ el: '#app', data(){ return { } }, template:` <App/> `, components: { App } })
main.css文件:
body{ background-color: red; }
还在src引入vue.js文件:
npm install vue -S
在根目录中构建各类配置文件:package.json、wabpack.conf.js、wabpack.dev.conf.js、wabpack.prod.conf.js。
在根目录中构建index.html模板文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模块的基本使用</title> </head> <body> <div id="app"></div> </body> </html>
在根目录建立dist目录。distdistsd
$ npm install html-webpack-plugin -D
调整webpack.config.js配置文件,将插件添加到webpack配置中:
// node.js中内容模块 var path = require('path'); var HtmlWebpackPlugin = require('html-webpack-plugin'); // html-webpack-plugin module.exports = { // entry入口 entry: { main: './src/main.js' }, // output出口 output: { path:path.resolve('./dist'), // 相对转绝对 filename: './bundle.js' }, watch:true, // 模块中的loader module:{ loaders:[ { test:/\.css$/, // css结尾的 loader:'style-loader!css-loader' // 依次识别 } ] }, // 插件 plugins:[ new HtmlWebpackPlugin({ template: './index.html', // 参照模板,以这个文件为参照物生成到dist目录 }) ] }
注意做为模板参照的index.html里去除以前bundle.js的引入。
执行npm run dev/build 来分别给生产环境和开发环境打包
$ npm run build
执行完成后,能够看到dist目录下多出了两个文件:bundle.js 和 index.html。具体index.html内容以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模块的基本使用</title> </head> <body> <div id="app"></div> <script type="text/javascript" src="./bundle.js"></script></body> </html>
显示效果以下所示:
安装http-server(必需要有node和npm):
$ npm install -g http-server
启动服务:
找到你的文件夹,在当前文件夹下打开命令行,输入http-server,默认启动是8080端口。
$ hs -o -p 8890
自动打开浏览器显示效果以下所示:
webpack 提供 webpack-dev-server 来解决自动刷新浏览器的问题。它是一个基于 expressjs的开发服务器,提供实时刷新浏览器页面的功能。
在项目下安装 webpack-dev-server:
$ npm install webpack-dev-server -D
下载完成后package.json中出现对应信息:
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack --config ./webpack.dev.config.js", "build": "webpack --config ./webpack.prod.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^2.1.1", "html-webpack-plugin": "^3.2.0", "style-loader": "^0.23.1", "webpack": "^3.12.0", "webpack-dev-server": "^3.3.1" } }
在这个版本下,运行 npm run dev 须要有 webpack-cli。老版本则不须要:
$ npm install webpack-dev-server@2.9.0 -D
执行后修改 package.json内容以下所示:
"devDependencies": { "css-loader": "^2.1.1", "html-webpack-plugin": "^3.2.0", "style-loader": "^0.23.1", "webpack": "^3.12.0", "webpack-dev-server": "^2.9.0" } }
--hot:热承载,页面数据修改自动刷新
--open:自动打开网页
{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack-dev-server --open --hot --inline --config ./webpack.dev.config.js", "build": "webpack --config ./webpack.prod.config.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^2.1.1", "html-webpack-plugin": "^3.2.0", "style-loader": "^0.23.1", "webpack": "^3.12.0", "webpack-dev-server": "^2.9.0" } }
此时执行以下命令,会自动在浏览器打开 http://localhost:8080页面
$ npm run dev
修改App.js中内容保存后,页面显示自动刷新。