// webpack.config.js
var CleanWebpackPlugin = require('clean-webpack-plugin');
配置plugins:
// webpack.config.js
...
plugins:[
new CleanWebpackPlugin(['dist'], {
root: '', // An absolute path for the root of webpack.config.js
verbose: true,// Write logs to console.
dry: false // Do not delete anything, good for testing.
}),
]
...
// webpack.config.js
...
plugins: [
// Enable multi-pass compilation for enhanced performance
// in larger projects. Good default.
new webpack.HotModuleReplacementPlugin({
multiStep: true
}),
],
devServer: {
// Enable history API fallback so HTML5 History API based
// routing works. This is a good default that will come
// in handy in more complicated setups.
historyApiFallback: true,
// Unlike the cli flag, this doesn't set
// HotModuleReplacementPlugin!
hot: true,
inline: true,
// Display only errors to reduce the amount of output.
stats: 'errors-only',
host: "localhost", // Defaults to `localhost` process.env.HOST
port: "8080", // Defaults to 8080 process.env.PORT
}
...
// ~/mockServer/server.js
var http = require('http');
var content = '▍if you see that,It means you have get the correct data by backend server(mock data by nodejs server)!';
var srv = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'application/text'});
res.end(content);
});
srv.listen(8888, function() {
console.log('listening on localhost:8888');
});
接下来我们需要这样配置去调用这个nodejs 的服务。
首先将热更新配置的代码修改为:
// webpack.config.js
...
plugins: [
// Enable multi-pass compilation for enhanced performance
// in larger projects. Good default.
new webpack.HotModuleReplacementPlugin({
multiStep: true
}),
],
devServer: {
// Enable history API fallback so HTML5 History API based
// routing works. This is a good default that will come
// in handy in more complicated setups.
historyApiFallback: true,
// Unlike the cli flag, this doesn't set
// HotModuleReplacementPlugin!
hot: true,
inline: true,
// Display only errors to reduce the amount of output.
stats: 'errors-only',
host: "localhost", // Defaults to `localhost` process.env.HOST
port: "8080", // Defaults to 8080 process.env.PORT
proxy: {
'/devApi/*': {
target: 'http://localhost:8888/',
secure: true,
/*
* rewrite 的方式扩展性更强,不限制服务的名称
* */
rewrite: function (req) {
req.url = req.url.replace(/^\/devApi/, '');
}
}
}
}
...
这篇文章将介绍如何利用 webpack 进行单页面应用的开发,算是我在实际开发中的一些心得和体会,在这里给大家做一个分享。
关于这个单页面应用大家可以结合这个实例去看。下面介绍的内容如果大家觉得这篇文章有不妥的地方,还请指出😂。
项目目录
我将根据这个目录结构进行讲解
项目的使用
建议先运行一下这个项目,有一个大致的了解,再往下阅读。使用说明:
区分开发、热更新、发布模式
开发模式:
热更新模式:
发布模式:
我区分开发、热更新、发布模式是通过配置‘package.json’文件的运行命令,有些人是通过创建多个不同的webpack的配置文件来达到想要的效果。
像这个项目就是使用了多个webpack的配置文件。
配置命令
这是在 package.json 文件中配置的
配置好了package.json文件,我们就可以这样运行
配置变量标识
配置完了命令,当我们运行不同的命令时,我们可以通过‘process.env.npm_lifecycle_event’去获取当前运行的命令,根据不同的命令,我们可以按照自己的需要做相应的处理。比如开发模式时,允许开启调试,静态资源不要压缩;发布模式时,不允许调试,静态资源要压缩。具体如下:
基础配置
配置路径
为了方便我们频繁使用路径,如下配置
配置别名
webpack的别名的目的就是简化我们的操作,引用资源时直接使用别名即可(和 seajs 里的别名用法一样)。配置如下:
配置webpack编译入口
配置webpack编译输出
提取css到单独的文件
当我们在js文件中通过require('')引用js时,webpack 默认会将css文件与当前js文件打包一起,但是这种方式会阻塞页面的加载,因为css的执行要等待js文件加载进来。所以我们会把css从js文件中提取出来,放到一个单独的css文件中。这时我们要使用webpack的插件:extract-text-webpack-plugin,配置如下:
引入插件
配置 loader
配置 plugins
公共js打包
项目中,我们通常会有公共的js,比如 jquery、bootstrap、underscore 等,那么这时候我们需要将这些公共的js单独打包。这时我们需要用webpack自带的插件:
资源添加版本号
项目上线后,资源的版本号十分重要。资源没有版本号,即使重新发布,客户端浏览器可能会把老的资源缓存下来,导致无法下载最新的资源。webpack 支持给资源添加版本号,不仅仅是js、css,甚至font、img都可以添加版本号。我们可以通过webpack中的‘chunkhash’来解决。
首先要了解下webpack 中 [hash]、[chunkhash]、[chunkhash:8]的区别。
资源加版本号,那么我们的输出的部分都要做改动,并且要区分当前的命令模式,如下:
输出公共js的地方也要改动:
页面自动引入含有版本号的文件
有个版本号后,我们考虑如何通过html引用这些含有版本号的js、css、font、img。webpack每次编译后的资源 chunkhash 会随着内容的变化而变化,所以我们不可能每次都手动的更改html这些资源的引用路径。这时我们要用到webpack的插件:html-webpack-plugin。这个插件的目的是生成html,也可以根据模板生成html,当然还有其他的功能,具体看插件介绍。下面是的配置:
引入插件
配置 plugins,生成需要的html
我们前面说过,webpack 默认只识别 js 文件,所以对于html也要使用对应的loader:
引用图片和字体
引用图片和字体,需要对应的loader,并且可以设置这些资源大小的临界值,当小于临界值的时候,字体或者图片文件会以base64的形式在html引用,否则则是以资源路径的形式引用。如下:
资源文件的压缩
js、css、html的压缩是少不了的,webpack 自带了压缩插件,如果某些对象名称不想被压缩,可以排除不想要压缩的对象名称。配置如下:
使用jquery、underscore
通过webpack编译输出后的项目中,虽然页面已经引用了jquery、underscore,但是还是无法直接使用‘$’、‘_’对象,我们可以这样:
但是这样实在不方便,如果我们就是要使用‘$’、‘_’对象直接操作,webpack 内置的插件可以帮我们解决。具体如下:
代码分割,按需加载
在单页面应用中,当我们加载其他的模板文件时,想要引用这个模板文件对应的js。如果我们通过这种方式require(),那么webpack会将这个模板文件对应的js也会和当前js打包成一个js。如果项目比较大,那么js文件也将越来越大。我们希望的是加载模板文件的时候动态的引用这个模板文件对应的js。那么我们可以通过 require.ensure()的方式。
比如现在有两个导航菜单:
我们给这两个菜单绑定点击事件,当点击‘home’时引用对应的‘home.js’;当点击‘HRM’时引用对应的‘hrm.js’,那么大致可以这样:
全局环境变量
有时我们只有在开发过程中,才想输出log日志。可以用以下webpack内置的插件解决:
这时代码中就可以这么写了:
清空发布目录
发布前清空发布目录是有必要的,我们可以通过‘clean-webpack-plugin’插件解决:
引入插件:
配置plugins:
热更新结合后端服务
热更新
热更新可以在你代码改变的时候即时编译输出,不用每次都要从都重新编译一遍,并且除了第一次编译比较慢,后面的编译都是增量编译,速度很快。有了这个功能,我们就不需要,每次都从头编译一次了。配置如下:
这时我们只要打开浏览器,输入:localhost:8080/ 就能看到结果,并且在你修改某些源文件后,浏览器会自动刷新,就能看到webpack 即时编译输出的结果,而不需要重新编译。
结合后端服务
我们在使用webpack开发时难免要结合后端服务开发,比如我们用webstorm 编译器开发项目,需要调用java的服务,由于有同源策略问题,这时我们会收到相关报错信息。这时我们可以通过代理的方式绕过同源策略。 这里我用nodejs 模拟一个后端服务,如下:
接下来我们需要这样配置去调用这个nodejs 的服务。 首先将热更新配置的代码修改为:
然后配置一个全局的环境变量,通过
DefinePlugin
:最后在调用服务的地方,只需要在调用地址前添加
__DEVAPI__
全局环境变量即可,如:这样在热更新的模式下,当有
__DEVAPI__
的地方就会自动识别为/devApi/
,而这里会通过代理处理帮你重写掉,绕过同源策略。自动打开浏览器
虽然以上的工作几乎已经满足我们对webpack的要求了,但是我们还想懒一点,想在热更新模式下,编译完成后自动打开浏览器。那么我们可以通过这个插件open-browser-webpack-plugin解决:
引用插件
配置插件,这个配置要根据项目的具体情况去配置:
总结
以上就是这篇文章的主要内容,希望通过这篇文章能够给大家带来一些启发。如果有觉得哪里不对,或者不合理的地方,欢迎指出。