// 一个常见的`webpack`配置文件
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
output: {
path: __dirname + "/build",
filename: "bundle-[hash].js"
},
devtool: 'none',
devServer: {
contentBase: "./public", //本地服务器所加载的页面所在的目录
historyApiFallback: true, //不跳转
inline: true,
hot: true
},
module: {
rules: [{
test: /(\.jsx|\.js)$/,
use: {
loader: "babel-loader"
},
exclude: /node_modules/
}, {
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [{
loader: "css-loader",
options: {
modules: true,
localIdentName: '[name]__[local]--[hash:base64:5]'
}
}, {
loader: "postcss-loader"
}],
})
}
}
]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'),
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin("style.css")
]
};
什么是Webpack
现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,前端社区涌现出了很多好的实践方法:
- 模块化,让我们可以把复杂的程序细化为小的文件;
- 类似于TypeScript这种在JavaScript基础上拓展的开发语言:使我们能够实现目前版本的JavaScript不能直接使用的特性,并且之后还能转换为JavaScript文件使浏览器可以识别;
- Scss,less等CSS预处理器
这些改进确实大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理又是非常繁琐的,这就为WebPack类的工具的出现提供了需求。
webpack和Grunt、Gulp的比较
- webpack是基于Node.js开发出的一个前端项目构建工具。.vue是在webpack中定义组件的方式,main.js是项目的JS入口文件。
- Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
- Gulp/Grunt是一种能够优化前端的开发流程的工具。它们的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,工具之后可以自动替你完成这些任务。
- Gulp是基于task任务的构建工具,小巧灵活;webpack是基于整个项目的模块化的解决方案。借助于webpack,可以完美实现资源的合并、打包、压缩、混淆、处理依赖关系等诸多功能,在很多场景下可以替代Gulp/Grunt类的工具。
使用Webpack
- 项目初始化,会自动生成package.json文件
//初始化
npm init
- 在项目安装webpack作为依赖包
//全局安装
npm install -g webpack
//安装到你的项目目录
npm install --save-dev webpack
- 在终端中使用webpack
对入口文件(main.js)做处理,生成一个打包文件(bundle.js)。指定入口文件后,webpack将自动识别项目所依赖的其它文件,不过需要注意的是如果你的webpack不是全局安装的,那么当你在终端中使用此命令时,需要额外指定其在node_modules中的地址
//webpack全局安装的情况
webpack .\src\main.js .\dist\bundle.js
//webpack非全局安装的情况
node_modules/.bin/webpack .\src/main.js .\dist/bundle.js
- 通过配置文件来使用webpack
为了不用每次修改代码后都要通过终端命令对bundle.js进行更新,通过定义一个配置文件webpack.config.js来实现上步功能,然后只需在终端执行webpack(非全局安装需使用node_modules/.bin/webpack)命令可自动生成bundle.js文件
const path = require('path') //定义根目录
module.exports = {
entry: path.join(__dirname,'./src/main.js') //入口,表示要使用webpack打包哪个文件
output:{ //输出文件相关的配置
path: path.join(__dirname,'./dist') //打包后文件存放的地方
filename: 'bundle.js' //打包后输出文件的文件名
}
}
- 更快捷的执行打包任务
在命令行中输入命令需要代码类似于node_modules/.bin/webpack这样的路径其实是比较烦人的,不过值得庆幸的是npm可以引导任务执行,对npm进行配置后可以在命令行中使用简单的npm start命令来替代上面略微繁琐的命令。在package.json中对scripts对象进行相关设置即可,设置方法如下。
{
"name": "webpack-sample-project",
"version": "1.0.0",
"description": "Sample webpack project",
"scripts": {
"start": "webpack" // 修改的是这里,JSON文件不支持注释,引用时请清除
},
"author": "zhang",
"license": "ISC",
"devDependencies": {
"webpack": "3.10.0"
}
}
注:
- package.json中的script会安装一定顺序寻找命令对应位置,本地的node_modules/.bin路径就在这个寻找清单中,所以无论是全局还是局部安装的Webpack,你都不需要写前面那指明详细的路径了。
- npm的start命令是一个特殊的脚本名称,其特殊性表现在,在命令行中使用npm start就可以执行其对于的命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}如npm run build
- webpack帮我们打包生成的bundle.js文件,并没有存放到实际的物理磁盘上,由于每次保存代码后都要更改bundle.js所以为了访问速度快些而是直接托管到了电脑的内存中,所以,我们在项目根目录中,根本找不到这个打包好的bundle.js
Webpack的强大功能
- Source Maps:让调试更容易
webpack在打包时生成了source maps,这位我们提供了一种对应编译文件和源文件的方法,使得编译后的代码可读性更好,更容易调试。在webpack配置文件中配置source maps,需要配置devtool。
对小到中型的项目中,eval-source-map是一个很好的选项,再次强调只应该开发阶段使用它,我们对webpack.config.js,进行如下配置:
module.exports = {
devtool: 'eval-source-map',
entry: __dirname + "/app/main.js",
output: {
path: __dirname + "/public",
filename: "bundle.js"
}
}
- 使用webpack构建本地服务器:监听代码的修改,并自动刷新显示修改后的结果
(1)webpack提供了一个基于node.js构建的本地开发服务器devserver,可以实现上述需求。不过它是一个单独的组件,在webpack配置前需要对其安装作为项目依赖。
npm install --save-dev webpack-dev-server
(2)修改webpack.config.js配置文件
devserver作为webpack配置选项中的一项,配置参数如下:
–open //自动打开浏览器
–port 3000 //问3000端口
–contentBase src //src做为根路径
–hot //热更新:局部更新,同时起到浏览器的无刷新浏览(仅对于样式,异步刷新页面有效)
module.exports = {
devtool: 'eval-source-map',
entry: __dirname + "/app/main.js",
output: {
path: __dirname + "/public",
filename: "bundle.js"
},
devServer: {
contentBase: "./public",//本地服务器所加载的页面所在的目录
historyApiFallback: true,//不跳转
inline: true//实时刷新
}
}
- Loaders
通过使用不同的loader,webpack有能力调用外部的脚本或工具,实现对不同格式的文件的处理,比如说分析转换scss为css,或者把下一代的JS文件(ES6,ES7)转换为现代浏览器兼容的JS文件
Loaders需要单独安装并且需要在webpack.config.js中的modules关键字下进行配置,Loaders的配置包括以下几方面:
(1)test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)
(2)loader:loader的名称(必须)
(3)include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
(4)query:为loaders提供额外的设置选项(可选)
- Babel
Babel其实是一个编译JavaScript的平台,它可以编译代码帮你达到以下目的:
(1)让你能使用最新的JavaScript代码(ES6,ES7…),而不用管新标准是否被当前使用的浏览器完全支持;
(2)让你能使用基于JavaScript进行了拓展的语言,比如React的JSX;
Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析Es6的babel-env-preset包和解析JSX的babel-preset-react包)。
-
CSS
(1)工具样式表css-loader、style-loader
(2)CSS module
(3)CSS预处理器
Sass 和 Less 之类的预处理器是对原生CSS的拓展,它们允许你使用类似于variables, nesting, mixins, inheritance等不存在于CSS中的特性来写CSS,CSS预处理器可以这些特殊类型的语句转化为浏览器可识别的CSS语句 -
插件(Plugins)