Webpack 学习
说明
最近学习了一下webpack,结合react 试验了一下,跟 使用 gulp 比,各有优缺点,公司暂时没有打算使用 webpack 开发,所以学的不是很深入,这里,总结了一下学习成果,其他一些高级用法,慢慢再来学习。
简介
webpack 用来构建大型单页面应用,所有资源都可以看做是模块
webpack 的前身 browserify
在webpack 中 一切都是模块,他是一个模块加载器、打包工具
Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个浏览器可识别的JavaScript文件。
安装webpack
1.安装webpack的命令环境
npm install webpack -g
先全局安装npm init
生成 package.jsonnpm install webpack --save-dev
本地安装npm install webpack-dev-server --save-dev
安装开发服务器
API
1.Loader
webpack 本身只能处理js 模块,如果要处理其他类型文件,需要用loader进行转换
使用loader后,我们就可以通过require来加载任何类型的模块或者文件loader 特性
- 通过管道的方式链式调用,每个loader把资源转换成任意格式并传递给下一个loader,但是最后一个loader必须返回js
- loader可以异步或者同步执行
2.配置文件(webpack.config.js)
写在项目根目录,可以有多个,然后通过 npm 的
scripts
约定按照那个配置文件执行webpack
3.插件(plugins)
用于扩展功能,下边是一些常用的插件,使用方法在最后的案例中
html-webpack-plugin
根据模板自动生成HTML,便于路径或者名称修改后的js和css插入extract-text-webpack-plugin
webpack会把css打包到js中,这个插件可以提取css为一个单独的文件copy-webpack-plugin
拷贝插件,用于将文件或者文件夹拷贝到其他位置webpack-md5-hash
webpack 本身可以铜鼓[hash]等方式添加MD5,但是在某些情况下会有问题,这个插件是一个增强插件autoprefixer
用于 css3 前缀自动补全,需要配合postcss-loader
使用webpack.DefinePlugin
用于设置环境变量webpack.optimize.UglifyJsPlugin
用于代码压缩webpack.optimize.CommonsChunkPlugin
抽取公共文件并打包为一个webpack.optimize.DedupePlugin
用于引用文件的去重
4.开发环境
5.热替换和热加载
webpack-dev-server的“hot” 和 “inline”选项
‘inline’为热加载功能,’hot’热替换,即尝试重新加载组件改变的部分(而不是重新加载整个页面)
,当两个参数都传入,当资源改变时,webpack会先尝试热替换,如果失败则重新加载整个入口页面
6.entry的取值
- 数组 : 添加多个彼此不互相依赖的文件
- 对象 : 可以为多页面应用添加,每个页面添加一个bundle.js
7.output
output 项,告诉webpack怎样存储输出结果以及存储到哪里,他有两个配置项
- path : 表示结果的存储位置
- pubicPath : 被许多webpack插件用于在生产模式下更新内嵌到css、html文件中的url值
8.’__dirname’
‘__dirname’是node.js 的一个全局变量,它指向当前执行脚本所在的目录
9.loader配置
Loaders需要单独安装并且需要在webpack.config.js下的modules关键字下进行配置,Loaders的配置选项包括以下几方面:
- test:一个匹配loaders所处理的文件的拓展名的正则表达式(必须)
- loader:loader的名称(必须)
- include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
- query:为loaders提供额外的设置选项(可选)
10.引入的node.js 模块 path
var path = require('path')
path.join([path1],[path2])
将多个路径结合在一起,并转化为标准化的路径
path.resolve([from...],to)
将to参数解析为绝对路径
完整例子
原本写了两个配置文件,案例主要是为了列举,所以把两个配置文件合并了,根据需要进行删减
var path = require('path'); // 引入node.js 的 path 模块
var webpack = require('webpack');
var HtmlwebpackPlugin = require('html-webpack-plugin'); // 自动生成 HTML
var ExtractTextPlugin = require('extract-text-webpack-plugin'); // 抽取 css,生成单独文件
var CopyWebpackPlugin = require('copy-webpack-plugin'); // 拷贝文件插件
var WebpackMdHash = require('webpack-md5-hash'); // 添加MD5版本号
var autoprefixer = require('autoprefixer'); // css3 前缀自动补全
//定义了一些文件夹的路径
var ROOT_PATH = path.resolve(__dirname); // 根路径
var APP_PATH = path.resolve(ROOT_PATH, 'app'); // 编译路径
var BUILD_PATH = path.resolve(ROOT_PATH, 'build'); // 生成文件路径
var TPL_PATH = path.resolve(ROOT_PATH, 'app/tpl.html'); // html模板所在路径
module.exports = {
devtool: 'cheap-module-source-map', // 配置生成source Map,用于开发调试
entry: { // 定义入口文件
app : path.join(APP_PATH, '/js/index.js'), // 入口文件
vendors: [ // 引入的类库单独打包
'react',
'react-dom'
],
},
output: { // 定义输出文件
path: BUILD_PATH, // 输出文件路径
filename: '/js/bundle.js?[chunkhash]', // 输出文件名 根据 entry
chunkFilename : 'chunk.js?[chunkhash]', // 没有列入 entry 中,但是需要被打包出来的文件名
publicPath : 'http://www.baidu.com/' // HTML中要引入的文件路径
},
module : {
preLoaders : [ // loader 执行前的操作
{test : /\.(js|jsx)/, loader : 'eslint',include: APP_PATH} // 使用 eslint 进行代码检查
],
loaders : [
{
test : /\.scss$/, // 用正则表达式匹配要处理的文件
loader : ExtractTextPlugin.extract('style','css!postcss!sass?outputStyle=expanded'),
/*
ExtractTextPlugin.extract() : 创建一个loader提取
第二个参数是loaders,用来处理编写的sass文件,postcss-loader 可以安转其他插件
*/
include: APP_PATH // 指定必须遍历的文件夹
},
{
test : /\.(png|jpe?g|gif)$/,
loader : 'url?limit=8192&name=/img/[name].[ext]?[hash:10]',
/*
limit :表示 小于指定大小的图片文件,会自动压缩为 base64 编码引用,大于指定大小,则正常打包
name : 表示打包后的文件名,也可以在这里设置路径
*/
include : APP_PATH
},
{
test : /\.(js|jsx)$/,
loader : 'babel', // babel 用来编译 es6 和 react,配置可以写在`.babelrc`文件中
/*
{
"presets": ["react", "es2015", "stage-1"],
"env": {
"development": {
"presets": ["react-hmre"]
}
},
"plugins": ["transform-object-assign"]
}
*/
include: APP_PATH
}
]
},
plugins: [ // 插件项
new webpack.DefinePlugin({ // 定义环境变量 ,(开发环境不要用)
"process.env": {
NODE_ENV: JSON.stringify("production")
}
}),
new WebpackMdHash(), // 使用MD5插件,(开发环境不要用)
//这个使用uglifyJs压缩你的js代码
new webpack.optimize.UglifyJsPlugin({ // 代码压缩插件,(开发环境不要用)
output: {
comments: false, // 输出的时候删掉所有注释
},
compress: {
warnings: false // 禁止警告
},
mangle: { // 排除不想要压缩的对象名称
except: ['$super', '$', 'exports', 'require', 'module', '_']
},
}),
// 把入口文件里面的数组打包成verdors.js,(可以有多个)
new webpack.optimize.CommonsChunkPlugin('vendors', '/js/vendors.js?[chunkhash]'),
new webpack.optimize.DedupePlugin(), // 去重,(开发环境不要用,增加编译时间)
new HtmlwebpackPlugin({ // 自动生成html
template: TPL_PATH, // 指定模板文件
title: 'Hello World app', // 重新写标题
filename: 'index.html', // 设置文件名
inject: 'body', // 把模板注入哪个标签后
favicon : './img/favicon.ico', //添加图标
minify : { // 是否压缩 false : 不压缩 | {} 设置压缩规则
removeComments:true, // 移除注释
collapseWhitespace:false // 去除空白
},
cache:false, // 是否缓存
}),
new ExtractTextPlugin("/css/styles.css?[contenthash]",{allChunks:true}),
/*
抽取 css ,
hash : 是根据编译对象计算所得,所有文件的hash都是一样的
chunkhash : 根据具体的模块文件计算所得,(css被引入了js中,算作js的一部分,虽然抽取出去了,但是还是计算在一起,所以给css设置chunkhash会和js一样)
contenthash : 表示文本文件内容的hash,也就是css 文件的hash
allChunks:true : 表示所有css文件打包到一个文件中
*/
new CopyWebpackPlugin( // 文件拷贝
[
{from : __dirname + '/app/_data', to : __dirname + '/build/_data'},
{from : __dirname + '/app/img', to : __dirname + '/build/img'}
],
{ignore : ['iconset.png']} // 排除选项
)
],
devServer : { // webpack-dev-server 配置,(生产环境不要使用)
contentBase : './dev/', // 开启服务的路径
outputPath : '/dev/', // 输出路径
historyApiFallback: true, // 设置可以从任意URL 访问
hot: true, // 开启热替换
inline: true, // 开启热加载
progress: true, // 显示进度
host : '0.0.0.0', // 代替 localhost ,可以在手机调试
port : 8080, // 配置端口号
open : true, // 服务开启的时候打开页面
noInfo : true, // 减少日志信息
},
resolve: {
root: [
path.resolve('./node_modules')
],
extensions : ['','.js','.jsx','.scss','.css','png','jpg','jpeg'],
},
eslint : {
configFile: './.eslintrc'
},
postcss : [
autoprefixer({ // 自动前缀补全
browsers : ['last 2 versions', 'Android >= 4.0']
}),
]
};
使用注意
在 入口文件中 引入scss
// index.js
import '../scss/index.scss';
在package.json 中 定义 命令
"start": "webpack --progress --colors ",
"dev": "webpack-dev-server --progress --profile --colors --hot --inline",
"build": "NODE_ENV='production' webpack --progress --profile --colors --quiet --config webpack.production.config.js"