软件工程的工程化开发概念由来已久,但对于前端开发来讲,咱们没有像VS或者eclipse这样量身打造的IDE,由于在大多数人眼中,前端代码无需编译,所以只要一个浏览器来运行调试就好了。可是时至今日,互联网特别是移动互联网为前端开发带来了更大的机会,同时前端代码也变得愈来愈复杂,愈来愈难以管理,所以前端工程化开发的工做能够说是刻不容缓。css
那么前端工程化开发到底须要解决哪些前端工程师们迫不及待的问题呢?我的认为至少包含如下几点:html
1. 专业的IDE支持,完成包括项目初始化,语法提示,项目编译,打包等工做。前端
2. 良好的模块化代码管理结构,模块化可使咱们编写的组件或者代码达到高度复用,下降代码间的耦合性;同时能够良好的与第三方组件兼容。node
3. 简单易配置的前端测试环境,完成组件的单元测试,页面的集成测试;同时提供良好的DEBUG环境,能够很好的定位错误的所在以及错误的详细信息。jquery
4. 静态资源(图片/字体/CSS/JS等)的良好管理方案,一是静态的文件版本问题,二是对于小图标自动转BASE64,减小HTTP请求webpack
5. 完整的代码版本管理,打包,发布,多环境部署,测试反馈等运维支持git
固然,以上只是我的意见。每一个公司、每一个项目的状况不同,所须要的条件都会有所不一样。github
以上这些需求,在之前基本上都是不敢想象的,这些工具都须要访问文件系统或者网络,不多有比较完整的解决方案。(好了,早期也有相似于Ant这样的Java解决方法,对前端开发人员要求太高并且不是很好用)好在,伟大的NodeJs诞生了,因而乎,基于NodeJs出现了不少优秀框架,像Grunt和 Gulp等。web
好了,今天的主题是webpack!让咱们来看下webpack做为后起之秀,是如何对前端工程化进行支持的!npm
你们注意,这里所说的动态生成HTML,是指咱们使用webpack来动态产生咱们最终所指望的HTML文件,而不是指在浏览器运行时使用JS生成HTML片断。
那为何要动态生成HTML,我本身写不行吗?答案固然是能够的。
之因此要动态生成,主要是但愿webpack在完成前端资源打包之后,自动将打包后的资源路径和版本号写入HTML中,达到自动化的效果。
你们能够回想一下咱们以前的三篇文章中介绍的案例,在那个练手的项目中,咱们页面上的script标签是咱们本身写的,那么若是咱们须要给JS添加上版本号的话,岂不是每次都的去修改?还有CSS,都是内嵌在JS中的,待JS加载后再建立style标签,而后写入css内容。这么作的话,浏览器须要先等待JS加载完成后,才能生成CSS样式,页面上会有一个等待过程,这个过程页面是彻底没有样式的。这固然不是咱们所想要的。
咱们的目标是:webpack根据指定的模板,插入打包编译后CSS文件路径;插入打包生成的JS的文件路径。而且还须要为两者添加版本号。另外,咱们还能够同时将HTML进行压缩,进一步减小文件大小。
咱们这里默认你们的开发环境已经安装了npm以及webpack,还没有安装的同窗能够自行安装。
A.新建一个空项目,而后经过 npm init 对项目进行初始化,按照提示输入项目的基本信息,而后生成package.json文件。这个文件里面会保存咱们即将安装的一些npm插件信息,便于二次移植开发。
B.安装项目所需依赖:
npm install css-loader jquery@1 style-loader html-webpack-plugin --save-dev
npm install extract-text-webpack-plugin --save-dev
依次为css加载器,jquery,style加载器,HTML生成插件以及文件提取插件。
最终package.json的依赖声明获得更新:
"devDependencies": { "css-loader": "^0.23.0", "extract-text-webpack-plugin": "^0.9.1", "html-webpack-plugin": "^1.7.0", "jquery": "^1.11.3", "style-loader": "^0.13.0", "webpack": "^1.12.9", "webpack-dev-server": "^1.14.0" }
准备就绪,咱们开始建立项目目录:
- webapp - src #代码开发目录 - css #css目录,按照页面(模块)、通用、第三方三个级别进行组织 + page + common + lib + img #图片资源 - js #JS脚本,按照page、components进行组织 + page + view #HTML模板 - dist #webpack编译打包输出目录,一样按照css/js/img进行组织 + css + js + view + node_modules #所使用的nodejs模块 package.json #项目配置 webpack.config.js #webpack配置 README.md #项目说明
dist目录也能够不建立任何子目录,这里为了方便查看,将js/css/html分开存放。
而后咱们在src目录建立几个测试文件,详细的代码你们能够前往https://github.com/xiaoyunchen/webpack/tree/master/src 查看源码。
咱们先来看下index.js的内容:
1 //引入CSS 2 require("../../css/lib/reset.css"); 3 require("../../css/common/global.css"); 4 require("../../css/page/index.css"); 5 6 document.write('Hello Index Js');
代码很简单,主要是引入了几个css文件。再看下咱们的 /view/index.html 这个模板的内容
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index主页</title> <meta name="author" content="https://github.com/xiaoyunchen/webpack"/> <meta name="date" content="2015-12-3"/> <meta name="description" content="基于webpack的前端工程化开发解决方案探索"/> <!-- 做者:https://github.com/xiaoyunchen/webpack 时间:2015-12-03 描述:head中无需再引入css以及facicon,webpack将根据入口JS文件的要求自动实现按需加载或者生成style标签 --> </head> <body> <p>Hello,Webpack!!</p> <!-- 做者:chyun532@qq.com 时间:https://github.com/xiaoyunchen/webpack 描述:body中一样无需单独引入JS文件,webpack会根据入口JS文件自动实现按需加载或者生成script标签,还能够生成对应的hash值 --> </body> </html>
这是一个简单的HTML模板,值得一提的是咱们在这里并无引入任何的CSS和JS,咱们但愿经过webpack打包来自动生成。(这里的模板还支持 Blueimp)
最后是咱们的重头戏,webpack.config.js,咱们将在这里配置一些webpack任务,来完成咱们的需求:
1 var path=require('path'); 2 var webpack = require('webpack'); 3 var ExtractTextPlugin = require("extract-text-webpack-plugin"); 4 var HtmlWebpackPlugin = require('html-webpack-plugin'); 5 module.exports={ 6 entry:{ 7 index:"./src/js/page/index.js", 8 }, 9 output:{ 10 path: path.join(__dirname,'dist'), 11 publicPath: "/webpack/dist/", 12 filename: "js/[name].js", 13 chunkFilename: "js/[id].chunk.js" 14 }, 15 module: { 16 loaders: [ //加载器 17 {test: /\.css$/, loader:ExtractTextPlugin.extract("style", "css") } 18 ] 19 }, 20 plugins:[ 21 new ExtractTextPlugin("css/[name].css"), //单独使用style标签加载css并设置其路径 22 new HtmlWebpackPlugin({ //根据模板插入css/js等生成最终HTML 23 favicon:'./src/img/favicon.ico', //favicon路径 24 filename:'/view/index.html', //生成的html存放路径,相对于 path 25 template:'./src/view/index.html', //html模板路径 26 inject:true, //容许插件修改哪些内容,包括head与body 27 hash:true, //为静态资源生成hash值 28 minify:{ //压缩HTML文件 29 removeComments:true, //移除HTML中的注释 30 collapseWhitespace:false //删除空白符与换行符 31 } 32 }) 33 ] 34 };
这个配置文件再以前的文章中咱们已经讲过不少次了,这里就不在赘述,只对其中几点比较关键的点进行分析:
17行:css加载器,只是这里改用了文件提取插件,将css提取出来单独做为一个文件进行存储。
21行:配置提取出来的css文件名以及存放路径
22行: html-webpack-plugin 这是webpack中生成HTML的插件,里面有详细的配置说明,你们能够前往查看。
23行:配置favicon,经过webpack引入同时能够生成hash值
24行:配置最终生成HTML文件存放路径
25行:咱们所使用的模板
26行:容许webpack修改哪些内容,可选值为head和body,true的话是均可以修改
27行:为静态资源生成hash值
28行:压缩最终生成的HTML文件,相关配置参数请前往 html-minifer 查看。(这里为了方便后面查看,没有移除HTML中的空白符与换行符。)
OK,下面咱们在项目的根目录下运行 webpack 打包命令完成项目打包:
打包成功后,咱们前往/dist/view目录下查看生成的index.html是什么样
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index主页</title> <meta name="author" content="https://github.com/xiaoyunchen/webpack"> <meta name="date" content="2015-12-3"> <meta name="description" content="基于webpack的前端工程化开发解决方案探索"> <link rel="shortcut icon" href="/webpack/dist/favicon.ico?69fed78822d5f8d3895c"><link href="/webpack/dist/css/index.css?69fed78822d5f8d3895c" rel="stylesheet"></head> <body> <p>Hello,Webpack!!</p> <script src="/webpack/dist/js/index.js?69fed78822d5f8d3895c"></script></body> </html>
能够看到生成的文件除了保留原模板中的内容之外,还根据入口文件index.js的定义,自动添加须要引入CSS与JS文件,以及favicon,同时还添加了相应的hash值。
运行这个文件,能够看到代码正常,引入的文件路径也都OK!
是的,咱们最初想要经过动态生成HTML的目的达到了。
webpack根据指定的模板,插入打包编译后CSS文件路径;
插入打包生成的JS的文件路径。而且还须要为两者添加版本号。
另外,咱们还能够同时将HTML进行压缩,进一步减小文件大小。
今天的分享就到这里。可能你们还有些疑问:按需加载的JS/CSS也会被提取出来吗?下一章咱们将继续探索这个问题。