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")可以直接引入
。