前言
《深入浅出webpack》里如是描述webpack:“Webpack是一个打包模块化 JavaScript 的工具,在 Webpack 切文件皆模块,通过 Loader 转换文件,通过 Plugin 注入钩子,最后输出由多个模块组合成的 文件。 Webpack 专注于构建模块化项目。”以此文章来记录一下webpack的常用配置。
HelloWorld
我们先来写几行简单的js代码
show.js
function show(content) { window.document.getElementById('app').innerText = `Hello,${content}` } module.exports = show
main.js
const show = require('./show.js') show('webpack')
现在来编写简单的 webpack.config.js
const path = require('path') module.exports = { mode: 'development', //webpack有两种模式,1生产模式production 2开发模式development entry: './src/index.js',//入口 output: { filename: 'bundle.js',//打包后的文件名 path: path.resolve(__dirname, './dist') //路径必须是一个绝对路径 } }
再创建一个html文件,把我们打包生成的bundle.js
引入其中,打开浏览器看看是不是符合预期效果
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title></head> <body> <div id="app"></div> <script src="./dist/bundle.js"></script> </body> </html>
如上所示,我们的打包是成功滴。
bundle.js
那我们再来看看它打包出来的文件是怎样的吧!
(function (modules){ // webpackBootstrap ```` } ({ "./main.js": (function (module, exports, __webpack_require__) { eval("const show = __webpack_require__(/*! ./show.js */ \"./show.js\")\r\nshow('webpack')\n\n//# sourceURL=webpack:///./main.js?"); }), "./show.js": (function (module, exports) { eval("function show(content) {\r\n window.document.getElementById('app').innerText = `Hello,${content}`\r\n}\r\nmodule.exports = show\n\n//# sourceURL=webpack:///./show.js?"); }) })
我们发现bundle.js
其实是一个自执行函数,参数为modules。而我们这里传入的参数是一个对象,key是我们文件的名字,value就是我们写的函数。我们再来详细看看里面做了什么事情。
首先一开始定义了一个 installedModules对象,用来作为缓存。
然后就是一个 __webpack_require__函数
function __webpack_require__(moduleId) { // 检查模块是否在缓存中,如果在就直接返回,一开始我们的模块是不在缓存中的,所以要走下面的逻辑 if (installedModules[moduleId]) { return installedModules[moduleId].exports; } // 创建一个新模块,并把它添加进缓存中,webpack是以moduleId来区分模块的 var module = installedModules[moduleId] = { i: moduleId, l: false,//是否已安装 exports: {} }; //call传入的函数 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); module.l = true; return module.exports; }
在一整个自执行函数的最后面有这么一句话
return __webpack_require__(__webpack_require__.s = "./main.js");
这里就开始了以main.js为入口开始安装依赖,再看回这个自执行函数传入的参数,又调用了一次__webpack_require__
方法,由此我们可以看出webpack会一直深度递归安装所有依赖。
webpack-dev-server
但是我们直接打开html文件这种做法似乎有点low,这里就可以用到这一个插件,它内置了一个express,可以帮我们启动一个本地服务。
此时的webpack.config.js
变成了这样
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { devServer: { //开发服务器的配置 port: 3000, //端口号 progress: true, //进度条 contentBase: './build', }, mode: 'development', entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, './dist') }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', filename: 'index.html', }) ]}
devServer里就是我们开发服务器中的配置,这里要注意的是我们要告诉它以那个目录为基本来启动这个开发服务器,所以我们要填写一个contentBase,除此之外呢,我们还要告诉它以哪个html文件为模板,这样它就可以帮我们把打包的js文件自动填充到模板中。
执行npx webpack-dev-server
后,打开localhost:3000就可以看到我们的页面了
这里其实我们还可以在package.json中配置两条脚本命令
"scripts": { "build": "npx webpack", "dev": " npx webpack-dev-server" },
这样我们就可以用npm run dev
来启动我们的开发服务了
样式处理
- 插入style标签
我们知道webpack打包出来的东西全是js,这里我们需要使用loader来做样式处理。
index.css
@import('./font-color.css') body {background-color: red}
font-color.css
body{color:pink}
index.js
require('./index.css')
在webpack.config.js
中,我们如是配置
module: { rules: [{ test: /\.css$/, use: ['style-loader', 'css-loader'] }] }
//css-loader 处理@import这种语法 style-loader 把样式插入到head标签中
在这里,css-loader
是用来处理@import
、url()
这种语法的,而style-loader
则将我们的样式插入到head标签中。值得一提的是,loader的执行顺序是数组内从右到左。
让我们来看看打包后的效果。
可以看到我们的css代码被插入到了head标签中。
- css抽离
那如果我们不想将太多样式直接插入其中,这里可以用到一个插件mini-css-extract-plugin
此时配置如下
module: { rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] }] } plugins: [ //抽离css样式 new MiniCssExtractPlugin({ filename: 'main.css' }) ],
这时打包后再来看index.html
,发现多了个link
标签,而此时的dist目录下也多了一个main.css
,对应上面我们的配置
后记
这里记录了一些webpack最基本的配置,希望继续学习下去之后,能有更多的东西记录与分享。如有错漏,恳请指出。您的批评和指正是我前进路上的一大动力。