前言
如今的很多网页其实可以看做是功能丰富的应用,它们往往拥有着复杂的JavaScript代码和一大堆依赖包。同时一个网页应用各个模块之间又会存在各种复杂的依赖关系。而webpack的出现则很好解决了上述问题。
1.webpack是什么?
首先引用官网的话来说
webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
而在我的理解看来webpack不仅仅是一个静态模块的打包器,实质上webpack是集前端自动化、模块化、组件化于一体的,你可以根据自己的需要来进行一系列的配置和安装一些插件,最终对你开发的应用进行打包和输出。
在这里我们将由一个小的demo来展示webpack最基础的一些配置。
2.webpack使用
初始化项目
我们先创建一个空的文件夹,然后在文件夹内执行以下操作
npm init //用npm初始化项目
npm install --save-dev webpack webpack-cli //安装webpack
// 注意因为在webpack 3中,webpack本身和它的CLI都是在同一个包中,但在webpack4中,已经将两者分开来更好地管理它们。所以这里要分别安装
执行完后在项目内新建一个src文件,在其文件目录下,新建两个文件
-
index.html
--存放在src目录下 -
index.js
--存放在src下的app文件内
在index.html中是我们传统网页中最基础的代码,在头部引入了jquery,同时还引入了另一个js文件
webpack-demo
在main.js中我们代码如下:
$('#app').html('hello world');
整个项目的目录结构如下:
在以上的demo中其实存在了两个问题
- 如果项目中引入的依赖项丢失,或者顺序错误,那么整个应用将不会运行
- 如果这些包含了依赖项但代码中并没有真正用到,那么在加载时,肯定会下载很多不必要的代码造成不必要的等待
而通过使用webpack,我们可以很好的解决上述的问题
重构代码
因为之前初始化项目的时候已经安装过webpack了,所以现在我们只需要安装jquery就行,在项目中执行如下命令:
npm install --save jquery
接下来我们改造一下main.js文件
const $jq = require('jquery');
$jq('#app').html('hello world');
这里我们直接在main.js里显示的引用了jquery,这样就不会存在隐式依赖的问,减少全局污染。
同理也要相应改造下index.html中的代码
webpack-demo
在这里去掉了head中引入jquery部分的代码,同时在文件中引入了最终通过webpack打包后生成的的bundle.js。
配置webpack
webpack其实拥有很多其它的功能,这些功能虽然都可以通过命令行模式实现,但是这样不仅不方便管理,还容易出问题,所以我们在本项目中定义一个配置文件,这个配置文件其实也是一个简单的JavaScript模块,我们可以把所有的与打包相关的信息放在里面。
继续上面的例子来说明如何写这个配置文件,在当前练习文件夹的根目录下新建一个名为webpack.config.js的文件,我们在其中写入如下所示的简单配置代码:
module.exports = {
entry: __dirname + '/app/main.js', //入口文件
output: {
path: __dirname + '/dist', //打包后的文件存放的地方
filename: 'bundle.js' //打包后输出文件的文件名
}
};
Webpack 启动后会从Entry里配置的Module开始递归解析 Entry 依赖的所有 Module。 每找到一个 Module, 就会根据配置的Loader去找出对应的转换规则,对 Module 进行转换后,再解析出当前 Module 依赖的 Module。 这些模块会以 Entry 为单位进行分组,一个 Entry 和其所有依赖的 Module 被分到一个组也就是一个 Chunk。最后 Webpack 会把所有 Chunk 转换成文件输出。 在整个流程中 Webpack 会在恰当的时机执行 Plugin 里定义的逻辑。
为了方便执行打包操作,我们还可以在package.json文件中对npm进行配置
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack" // 添加了start命令
},
现在只需要使用npm start就可以运行webpack命令将main.js打包输出为bundle.js了。
至此我们在浏览器刷新下页面就能看到网页的展示了
模块拆分
现在我们把main.js中的"hello world!"字符串放到另外一个const.js中,然后在main.js中引入使用,此时这就会涉及到webpack的模块拆分
我们修改下main.js中的代码
const $jq = require('jquery');
const str = require('./const.js');
$jq('#app').html(str);
在同目录下新增const.js
module.exports = 'hello wrold';
至此我们在const.js中导出了字符串,然后再main.js中通过require导入这个变量,再重新执行npm start
之后就能看到渲染出的界面
webpack构建本地服务器
上面的例子中,我们每次改完代码后都要重新执行一次命令才能看到修改后的结果,事实上,webpack也支持让你的浏览器监听你的代码的修改,并自动刷新显示修改后的结果。这就是webpack提供一个的本地开发服务器,我们在webpack中进行配置之前需要单独安装它
npm install --save-dev webpack-dev-server
然后我们修改下webpack.config.js
中的代码
module.exports = {
entry: __dirname + '/src/app/main.js', //入口文件
output: {
path: __dirname + '/dist', //打包后的文件存放的地方
filename: 'bundle.js' //打包后输出文件的文件名
},
devServer: {
contentBase: './dist', //本地服务器加载的页面所在的目录
open: true, // 启动后是否自动打开当前页
port: 8080, // 设置默认监听端口,如果省略,默认为”8080“
inline: true //设置为true,当源文件改变时会自动刷新页面
}
};
再在package.json
中的script中添加如下命令
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack",
"server": "webpack-dev-server"
}
配置后,在终端中输入npm run server,即可看到输出的信息
之后我们在代码上做的任何修改,浏览器监听到后,会自动帮我们刷新页面,实时显示最新的效果
3.webpack进阶
1.Loader
webpack 自身只理解 JavaScript文件,且只认为JavaScript文件是模块,但是我们通过loader可以 让 webpack 能够去处理那些非 JavaScript 文件。其实loader可以理解为webpack的编译器,它的作用就是让webpack可以处理一些非JavaScript文件,比如png、csv、xml、css、json等各种类型的文件,使用合适的loader可以让JavaScript的import导入非JavaScript模块。
在更高层面,在 webpack 的配置中 loader 有两个目标:
1.test
属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
-
use
属性,表示进行转换时,应该使用哪个 loader。
在webpack.config.js中:
module.exports = {
/........./
module: {
rules: [
{
test: /\.css$/,
use: 'css-loader'
}
]
}
};
以上配置中,对一个单独的 module 对象定义了 rules 属性,并且在里面包含第一条处理规则,其中含有两个必须属性:test 和 use。这就相当于与告诉webpack,当你碰到在 require()/import 语句中被解析为 '.css' 的路径时,在打包之前,先使用css-loader 转换一下。
2. Plugins
loader用于转换非JavaScript类型的文件,而插件可以用于执行范围更广的任务,包括打包、优化、压缩、搭建服务器等等,功能十分强大。要是用一个插件,一般是先使用npm包管理器进行安装,然后在配置文件中引入,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。
在webpack.config.js中:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
/........./
module: {
rules: [
{
test: /\.css$/,
use: 'css-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
3.Mode
在webpack升级到4之后,就新增了可以配置的模式(Mode),即可以通过配置对象的mode属性进行配置,主要值为production或者development。两种模式的区别在于一个是为生产环境编译打包,一个是为了开发环境编译打包。在生产环境模式下,webpack 内置的优化会自动对代码进行压缩等优化,省去了配置的麻烦。
module.exports = {
mode: 'production' // 或者development
};
结语
本文从一个小的入门例子出发,主要介绍了webpack入门的一些基本配置信息。所以这篇笔记也只是一篇基础入门的笔记,如果要真正的构建较为复杂的开发环境和生产环境,还需要自己去了解更多的loader和plugin配置。