WebPack 开发
WebPack 开发
如果你一直跟随之前的指南,应该对一些 webpack 基础知识有着很扎实的理解。在我们继续之前,先来看看如何建立开发环境,使我们的开发变得更容易一些。
本指南中的工具仅用于开发环境,请不要在生产环境中使用它们!
使用 Source Map
当 webpack 打包源时,可能会很难追踪到和警告在源中的原始位置。例如,如果将三个源(a.js, b.js 和 c.js)打包到 bundle(bundle.js)中,而其中源包含,那么堆栈跟踪就会简单地指向到 bundle.js。这并通常没有太多帮助,因为你可能需要准确地知道来自于哪个源。
为了更容易地追踪和警告,JavaScript 提供了 ,将编译后的映射回原始源。如果来自于 b.js,source map 就会明确的告诉你。
source map 有很多不同的选项可用,请务必仔细阅读它们,以便可以根据需要进行配置。
对于本指南,我们使用 inline-source-map 选项,这有助于解释说明我们的目的(仅解释说明,不要用于生产环境):
webpack.con.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = { entry: { app: './src/index.js', print: './src/print.js' }, + devtool: 'inline-source-map', plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Development' }) ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') } };
现在,让我们来做一些调试,在 print.js 中:
src/print.js
export default function printMe() { - console.log('I get called from print.js!'); + cosnole.error('I get called from print.js!'); }
运行 npm run build,就会编译为如下:
Hash: 7bf68ca15f1f2690e2d1 Version: webpack 3.1.0 Time: 1224ms Asset Size Chunks Chunk Names app.bundle.js 1.44 MB 0, 1 [emitted] [big] app print.bundle.js 6.43 kB 1 [emitted] print index.html 248 bytes [emitted] [0] ./src/print.js 84 bytes {0} {1} [built] [1] ./src/index.js bytes {0} [built] [3] (webpack)/buildin/global.js 509 bytes {0} [built] [4] (webpack)/buildin/module.js 517 bytes {0} [built] + 1 hidden module Child html-webpack-plugin for "index.html": [2] (webpack)/buildin/global.js 509 bytes {0} [built] [3] (webpack)/buildin/module.js 517 bytes {0} [built] + 2 hidden modules
现在在浏览器打开最终的 index.html ,点击按钮,并且在控制台查看的。应该如下:
Uncaught ReferenceError: cosnole is not defined at HTMLButtonElement.printMe (print.js:2)
我们可以看到,此包含有发生的(print.js)和行号(2)的引用。这是非常有帮助的,因为现在我们知道了,所要的问题的确切位置。
选择开发工具
一些文本编辑器具有“安全写入”,可能会干扰以下某些工具。阅读调整文本编辑器以这些问题。
每次要编译时,手动运行 npm run build 就会变得很麻烦。
webpack 中有几个不同的选项,可以帮助你在发生变化后编译:
webpack's Watch Mode
webpack-dev-server
webpack-dev-middleware
多数场景中,你可能需要使用 webpack-dev-server,但是不妨探讨一下以上的所有选项。
使用观察模式
你可以指示 webpack "watch" 依赖图中的所有以进行更改。如果其中被更新,将被重新编译,所以你不必手动运行整个构建。
我们用于启动 webpack 的观察模式的 npm script 脚本:
package.json
{ "name": "development", "version": "1.0.0", "description": "", "main": "webpack.con.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", + "watch": "webpack --watch", "build": "webpack" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "clean-webpack-plugin": "^0.1.16", "loader": "^0.28.4", "csv-loader": "^2.1.1", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.29.0", "style-loader": "^0.18.2", "webpack": "^3.0.0", "xml-loader": "^1.2.1" } }
现在,你可以在命令行中运行 npm run watch,就会看到 webpack 编译,然而却不会命令行。这是因为 script 脚本还在观察。
现在,webpack 观察的同时,我们先移除我们之前引入的:
src/print.js
export default function printMe() { - cosnole.log('I get called from print.js!'); + console.log('I get called from print.js!'); }
现在,保存并检查终端窗口。应该可以看到 webpack 重新编译后的模块!
唯一的缺点是,为了看到后的实际,你需要刷新浏览器。如果能够刷新浏览器就更好了,可以尝试使用 webpack-dev-server,恰好可以实现我们想要的。
使用 Webpack-Dev-Server
webpack-dev-server 为你提供了简单的 web 服务器,并且能够实时重新加载(live reloading)。让我们设置以下:
npm install --save-dev webpack-dev-server
,告诉开发服务器(dev server),在哪里:
webpack.con.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = { entry: { app: './src/index.js', print: './src/print.js' }, devtool: 'inline-source-map',+ devServer: {+ contentBase: './dist'+ }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Development' }) ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') } };
以上配置告知 webpack-dev-server,在 localhost:8080 下建立服务,将 dist 目录下的,作为可访问。
让我们 script 脚本,可以直接运行开发服务器(dev server):
package.json
{ "name": "development", "version": "1.0.0", "description": "", "main": "webpack.con.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "watch": "webpack --watch",+ "start": "webpack-dev-server --open", "build": "webpack" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "clean-webpack-plugin": "^0.1.16", "loader": "^0.28.4", "csv-loader": "^2.1.1", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.29.0", "style-loader": "^0.18.2", "webpack": "^3.0.0", "xml-loader": "^1.2.1" } }
现在,我们可以在命令行中运行 npm start,就会看到浏览器加载。如果现在和保存任意源,web 服务器就会重新加载编译后的。试一下!
webpack-dev-server 带有许多可配置的选项。转到相关文档以了解更多。
现在,服务器正在运行,你可能需要尝试模块热替换(Hot Module Replacement)!
使用 Webpack-Dev-Middleware
webpack-dev-middleware 是容器(wrapper),它可以把 webpack 处理后的传递给服务器(server)。 webpack-dev-server 在内部使用了它,同时,它也可以作为单独的包来使用,以便进行更多设置来实现更多的需求。接下来是 webpack-dev-middleware 配合 express server 的示例。
首先,安装 express 和 webpack-dev-middleware:
npm install --save-dev express webpack-dev-middleware
接下来我们需要对 webpack 的做一些调整,以确保中间件(middleware)能够正确启用:
webpack.con.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = { entry: { app: './src/index.js', print: './src/print.js' }, devtool: 'inline-source-map', plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Output Management' }) ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'),+ publicPath: '/' } };
publicPath 也会在服务器脚本用到,以确保资源能够在 http://localhost:3000 下正确访问,我们稍后再设置端口号。下一步就是设置我们的 express 服务:
project
webpack-demo |- package.json |- webpack.con.js+ |- server.js |- /dist |- /src |- index.js |- print.js |- /node_modules
server.js
const express = require('express');const webpack = require('webpack');const webpackDevMiddleware = require('webpack-dev-middleware');const app = express();const con = require('./webpack.con.js');const compiler = webpack(con);// Tell express to use the webpack-dev-middleware and use the webpack.con.js// conuration file as a base.app.use(webpackDevMiddleware(compiler, { publicPath: con.output.publicPath}));// Serve the files on port 3000.app.listen(3000, function () { console.log('Example app listening on port 3000!\n');});
现在, npm script,以使我们更方便地运行服务:
package.json
{ "name": "development", "version": "1.0.0", "description": "", "main": "webpack.con.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "watch": "webpack --watch", "start": "webpack-dev-server --open", + "server": "node server.js", "build": "webpack" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "clean-webpack-plugin": "^0.1.16", "loader": "^0.28.4", "csv-loader": "^2.1.1", "express": "^4.15.3", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.29.0", "style-loader": "^0.18.2", "webpack": "^3.0.0", "webpack-dev-middleware": "^1.12.0", "xml-loader": "^1.2.1" } }
现在,在你的终端执行 npm run server,将会有类似如下信息:
Example app listening on port 3000! webpack built 27b137af6d9d8668c373 in 1198ms Hash: 27b137af6d9d8668c373 Version: webpack 3.0.0 Time: 1198ms Asset Size Chunks Chunk Names app.bundle.js 1.44 MB 0, 1 [emitted] [big] app print.bundle.js 6.57 kB 1 [emitted] print index.html 306 bytes [emitted] [0] ./src/print.js 116 bytes {0} {1} [built] [1] ./src/index.js bytes {0} [built] [2] ./node_modules/lodash/lodash.js 540 kB {0} [built] [3] (webpack)/buildin/global.js 509 bytes {0} [built] [4] (webpack)/buildin/module.js 517 bytes {0} [built] Child html-webpack-plugin for "index.html": Asset Size Chunks Chunk Names index.html 544 kB 0 [0] ./node_modules/html-webpack-plugin/lib/loader.js!./node_modules/html-webpack-plugin/default_index.ejs 538 bytes {0} [built] [1] ./node_modules/lodash/lodash.js 540 kB {0} [built] [2] (webpack)/buildin/global.js 509 bytes {0} [built] [3] (webpack)/buildin/module.js 517 bytes {0} [built] webpack: Compiled successfully.
现在,打开浏览器,到 http://localhost:3000,你应该看到你的webpack 应用程序已经运行!
如果想要了解更多关于模块热替换(Hot Module Replacement)的机制,我们推荐你查看模块热替换(Hot Module Replacement)指南。
调整文本编辑器
使用编译时,可能会在保存时遇到一些问题。某些编辑器具有“安全写入”,可能会影响重新编译。
要在一些常见的编辑器中禁用此,请查看以下列表:
Sublime Text 3 - 在首选项(user preferences)中 atomic_save: "false"。
IntelliJ - 在首选项(preferences)中使用,查找到 "safe write" 并且禁用它。
Vim - 在设置(settings)中 :set backupcopy=yes。
WebStorm - 在 Preferences > Appearance & Behavior > Sy Settings 中取消选中 Use "safe write"。
结论
现在,你已经学会了如何编译,并运行简单的开发服务器(development server),你可以查看下指南,其中将介绍模块热替换(hot module replacement)。