webpack前端自动化构建方案

转载请注明原作者以及链接,谢谢!


我们项目的框架使用的是angular.js(v1.5.8)+ webpack,使用webpack主要是要想做到以下几点:
1.抛弃原来项目中的requireJs,gulp/grunt。模块化和打包均由webpack实现。
2.将项目资源大部分输出到一个bundle.js文件,减少浏览器首次加载时的资源请求数量。
3.使用npm安装框架依赖。不再引入项目中。避免项目代码提交时更改库代码。
4.进行代码压缩,并开启nginx的gzip,对代码再次进行压缩。
5.实现测试和生产环境使用不同的配置文件。
6.生成带有项目名称和版本号的文件夹并压缩(用于webApp)。
7.生成带有hash的bundle.js文件。可以解决浏览器因为缓存不刷新的问题(用于web项目)。

因为项目情况,没有用到es6,scss等。没有进行代码转换。如果需要转码,只要找到对应的loader。npm安装后加载进来就可以了,这里不会提到。另外,webpack我也没用多久。如果哪里写的不好或者写错了,请指点,谢谢!
先奉上webpack文档地址:webpack


▍第一步:搭建环境

安装node.js和npm

npm 是 javaScript的包管理工具,类似maven的依赖管理, 用它来下载我们需要的模块。
Node.js下载地址

创建package.json

npm init
在项目文件夹下新建一个package.json并填写项目信息,项目名称以及版本号等项目信息

npm安装插件

全局安装webpack:
npm install webpack -g
安装webpack-dev-server:
npm install webpack-dev-server -g
安装依赖到项目中并加入package.json
npm install [package] --save-dev/ npm install [package] --save
可能有时候会npm安装包比较慢甚至是安装不了,可以使用淘宝NPM镜像[cnpm]
删除依赖
npm uninstall [package]

▍第二步:编写webpack.config.js文件

代码:webpack+anuglar.js
目录结构:
webpack
|____app
| |____index.html
| |____index.js
|____package.json
|____webpack.config.js
|____zip.js
使用loader加载器对资源进行转换
module.exports = {
    entry: path.resolve(__dirname, "app", "index.js"),
    output: {
        path: "dist",
        filename: "bundle.[hash].js"
    },
    module: {
        loaders: [
            {
               test: /\.js$/,
               exclude: /node_modules/,
                loader:"ng-annotate"
            }, {
               test: /\.css$/,
               loader: "style!css!autoprefixer"
            }, {
               test: /\.html$/,  
               exclude: /node_modules/,
               loader:"html"
            }, {
               test: /\.(ttf|eot|otf)$/,
               loader: "file"
            }, {
               test: /\.woff(2)?$/,
               loader: "url?limit=8192&minetype=application/font-woff"
            }, {
               test: /\.(png|jpg|gif|svg)$/,
               loader: "url?limit=8192&name=images/[name].[ext]"
            }
        ]
    }
}
entry编译的入口Js文件。ouput文件输出定义

编译后的文件名bundle.[hash].js,这里用到hash。每一次进行webpack打包,都会生成一个hash值,用它为文件命名,能让每次生成的文件名都不一样。浏览器访问也不会存在缓存问题。path.resolve用来拼接路径,__dirname是指当前路径的绝对路径。

loader加载器的使用,如css-loader。

首先安装css-loader:npm install --save-dev css-loader
在配置文件中,通过正则绑定对应的loader, 可以省略loader,写成css/css-loader均可。使用!可以定义多个loader,?后边配置参数

ng-annotate-loader是用来处理angular.js的代码。这是一小段代码:
angular.module('myApp', [])
       .controller('testCtrl',  function ($scope) {});

$scope普通的压缩会把它当成参数压缩了。解决的方法,一种是写成数组

['$scope', function($scope) {}];
// 或者是
testCtrl.$inject = ['$scope'];

另外一种是使用ng-annotate。编译之后,会自动补全

angular.module('myApp', [])
       .controller('testCtrl',  ["$scope", function ($scope) {}]);
autoprefixer-loader可以补全css代码
图片base64编码

图片这里使用url-loader,会过滤图片。
limit=8192 : 将图片大小小于8K的转为base64编码。
name=images/[name].[ext] : 大于8k的图片则存放到dist/images底下。

webpack sourcemap

调试的时候可能需要知道这个页面对应了哪些文件。这里就要用到sourcemap。可以使用命令webpack -d去生成,或者在webpack.config.js中配置devtool
其实调试很多时候主要还是看样式来自哪个文件。所以这里简单一点,如果是测试环境。css-loader文件后边加上sourcemap。这样子编译的文件小,速度也快一些。我有时候配置devtool不起效果。也不知道为什么。
{ test: /\.css$/, loader: "style!css?sourceMap!autoprefixer" }

生成index.html

每一次生成的bundle.js文件因为带有hash,所以都是不同的。不能在index.html里边直接引入。这里要用到一个插件html-webpack-plugin根据模板生成index.html页面(github地址)。
安装:npm install html-webpack-plugin --save-dev
引入:var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    ...
    plugins: [                                       
        new HtmlWebpackPlugin({        
            filename: path.resolve([输出路径], 'index.html'),
            template: path.resolve([输入路径], "index_template.html")
        })
    ]
}

在模板index_template.html不需要引入bundle.js。生成index.html会自动引入。

▍第三步:编译打包项目工程

webpack常用指令:
$ webpack        // 最基本的启动webpack方法
$ webpack -w     // 提供watch方法,实时进行打包更新
$ webpack -p     // 对打包后的文件进行压缩
$ webpack -d     // 提供source map,方便调试。
环境配置(webpack.config.js)
"scripts": {
  "production": "set NODE_ENV=production && webpack -p",
    "test" : "set NODE_ENV=test && webpack"
}

执行npm run production / npm run test
这是以前的做法。通过设置环境变量NODE_ENV来判断打包的环境。在webpack.config.js中通过process.env.NODE_ENV获取这个值。
发现在mac上是可以的,但在windows底下。scripts中使用&&是有问题的。后来改了一下。直接把webpack -p这个指令当做生产环境。其他视为调试。

获取到指令的第二个参数,为-p则判断为生产环境。
var isProductEnv = process.argv[2] === '-p';

然后可能需要不同环境配置一些变量。比如说HTTP请求的地址。因为这些都属于项目的内容。就不想在webpack.config.js中配置。直接配置到app文件夹中。在项目中判断当前环境,require对应的JSON数据。

// webpack.config.js
var DefinePlugin = require('webpack').DefinePlugin;
var definePlugins = new DefinePlugin({
    webpack_prod : isProductEnv
});
module.exports = {
    ...
    plugins: [                                       
        definePlugins,
        ...
    ]
}
// index.js
if (webpack_prod) {
    require('./env/product');
} else {
    require('./env/test');
}
webpack-dev-server本地webserver

启动:webpack-dev-server
地址:http://localhost:port/webpack-dev-server/dist/index.html
文档地址 :webpack-dev-server文档
端口号默认是8080,可以在devServer中更改。每次改代码保存后,会自动编译并且刷新页面。还可以做到热替换即不刷新页面可以更新。除此之外还有一个proxy功能可以用来配置代理。

压缩成项目名称_版本号.zip

使用node.js的插件zip-local
安装并加入项目中:
npm install zip-local --save-dev
项目目录下建立zip.js文件

// 从package.json文件中获取到项目名称和版本号
var packageInfo = require('./package.json');
var zip = packageInfo.name + "_" + packageInfo.version;
// 引入插件
var zipper = require('zip-local');
// 压缩dist文件夹
zipper.sync.zip("dist/").compress().save(zip + ".zip");

执行命令行 node zip 生成zip压缩文件。

▍第四步:开启nginx的gzip功能

webpack打包编译后成一个文件,文件会比按需加载大。web项目在第一次加载的时候,文件太大的话会比较慢。所以要想办法把它的体积变小再变小。

未压缩前,执行命令webpack

![](https://github.com/n98745/MarkdownPhotos/blob/master/webpack/3D5D26AE-AD6E-464E-8AB6-04490118096A.png?raw=true =100x100)

先使用webpack自带的压缩,执行命令webpack -p

![](https://github.com/n98745/MarkdownPhotos/blob/master/webpack/20E389BE-0ABB-405D-8DD4-08B94D599BD1.png?raw=true =100x100)

开启nginx的gzip功能

官方文档:Module ngx_http_gzip_module
翻译:Nginx官方文档翻译--ngx_http_gzip_module模块

gzip on;
gzip_proxied any;
gzip_disable "msie6";
gzip_comp_level 3;
gzip_min_length 4k;
gzip_types text/css text/xml application/javascript;
开启后:

![](https://github.com/n98745/MarkdownPhotos/blob/master/webpack/5C448E36-480C-4071-8240-33BC35A48896.png?raw=true =100x100)
这样子就把我们刚刚接近2M的项目代码压缩到150Kb。

▍webpack模块化

webpack支持CommonJs和AMD规范。前者是同步加载,后者是异步加载。webpack加载的对象是module。它把静态资源都当做是模块。不仅仅只是js。还有css、html、图片等等都可以通过require去引入,如引入图片:

var img = document.createElement("img");
img.src = require("../image/xxx.jpg");
document.body.appendChild(img);

模块输出:module.exports = ...

webpack resolve

这个是在webpack.config.js中去配置的一个对象。它的几个用法:

1. extensions
// 当后缀名为空的时候,会自动识别并不缺
resolve: { 
       extensions: ['', '.js'] 
}  
2. alias
// 通过别名可以减少打包时间,项目中直接require("consts")重定向到指定的文件。
resolve: { 
      alias: { 
          consts: path.resolve(__dirname, "app/util/constant.js")
      } 
} 
全局引入

有时候像jquery想要给它配置全局,使用$去引入。
首先安装依赖到项目中
npm install --save-dev jquery
配置plugins,然后就可以在项目中使用。

plugins:[
    new webpack.ProvidePlugin({
        $:"jquery"
    })
]
引入依赖

项目中要用到angular,npm install --save-dev angular把依赖下载到文件夹node_modules中。
通过require("angular")可以直接引入

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • 版权声明:本文为博主原创文章,未经博主允许不得转载。 webpack介绍和使用 一、webpack介绍 1、由来 ...
    it筱竹阅读 10,933评论 0 21
  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,084评论 7 35
  • 记得2004年的时候,互联网开发就是做网页,那时也没有前端和后端的区分,有时一个网站就是一些纯静态的html,通过...
    阳阳阳一堆阳阅读 3,193评论 0 5
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,616评论 7 110
  • 去阿智村的路,是一场绿色的盛宴。 两旁的群山,浓密到只见绿叶不见树干,路两旁的围栏上爬满藤蔓。仿佛长了几千年。这样...
    烟行阅读 427评论 0 1