FaceBook的Instagram团队开发的一个前端打包工具,比起之前的一些前端自动化构建工具,比如Gulp和Grunt来说,Webpack是基于依赖来进行代码整合的。也就是必须要有一个入口文件,这个入口文件中会引入其他的脚本文件,之后webpack通过这些依赖关系将所有的文件打包,并且可以自动生成sourcemap来方便调试。
基本的开发环境首先需要安装node、npm这些就不多说了,然后需要使用npm安装webpack以及typescript。具体的使用方法可以参考两个的官方文档:
首先建立项目的目录结构:
mkdir WebpackProject
cd WebpackProject
mkdir src
mkdir dist
cd src
mkdir components
得到如下的目录结构:
首先初始化npm
npm init
一路上看着填写就可以了,如果只是试验环境的话可以一路Enter下去。
安装webpack以及typescript:
npm install -g webpack typescript
现在国内的npm速度比较慢,可以使用阿里自己搭建的国内的npm镜像站:cnpm来进行依赖安装。
安装react相关的依赖:
npm install --save-dev react react-dom @types/react @types/react-dom
在构建开发环境的时候,需要一些webpack插件来协助完成代码打包,由于我们使用了typescript这种JavaScript的super set来进行开发,所以要安装webpack的typescript解析工具,并且在现在这种自动化构建工具构建的代码中,代码都是经过压缩或者打包的,也就是在错误提示的时候,根本不知道错误究竟出现在哪里,所以现在chrome支持了sourceMap来对代码进行定位,这里sourceMap就不具体解释了,有兴趣的同学可以自己上网搜索一下。
安装webpack的依赖工具:
npm install --save-dev ts-loader source-map-loader
npm link typescript
npm install --save-dev webpack-dev-server
这时所有的依赖都安装完了,现在可以根据自己的需求初始化一下git或者bower。
在使用typescript的时候可以自己指定其一些配置:
tsc --init
通过上面的命令生成typescript的配置文件:tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"jsx": "react"
},
"files": [
"./src/components/Hello.tsx",
"./src/index.tsx"
]
}
看到files数组里面我们放了两个文件,这两个文件中index.tsx作为入口文件,Hello.tsx文件作为引入的内容:
index.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Hello } from "./components/Hello";
ReactDOM.render(
<Hello compiler="TypeScript" framework="React" />,
document.getElementById("example")
);
Hello.tsx
import * as React from "react";
export interface HelloProps { compiler: string; framework: string; }
export class Hello extends React.Component<HelloProps, {}> {
render() {
return <h1>Hello from {this.props.compiler} and {this.props.framework}!</h1>;
}
}
然后配置webpack的配置文件:
webpack.config.js
var path = require("path");
module.exports = {
//入口文件的路径
entry: "./src/index.tsx",
output: {
//打包的输出路径
path: path.resolve(__dirname,"dist"),
filename: "bundle.js",
},
// 启用sourceMap
devtool: "source-map",
resolve: {
// 添加需要解析的文件格式
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
//加载的模块,这里包括ts和source-map
module: {
loaders: [
{ test: /\.tsx?$/, loader: "ts-loader" }
],
preLoaders: [
{ test: /\.js$/, loader: "source-map-loader" }
]
},
//webpack的本地服务器webpack-dev-server的配置
devServer: {
contentBase: "./",
colors: true,
historyApiFallback: true,
inline: true
},
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
};
在工程根目录中添加一个index.html的html文件,来引入webpack生成的打包好的文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
</head>
<body>
<div id="example"></div>
<!-- Dependencies -->
<script src="http://localhost:8080/webpack-dev-server.js"></script>
<script src="./node_modules/react/dist/react.js"></script>
<script src="./node_modules/react-dom/dist/react-dom.js"></script>
<!-- Main -->
<script src="./dist/bundle.js"></script>
</body>
</html>
在根目录下面运行:
webapck
可以看到生成了一个bundle.js文件为打包好的脚本文件:
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var React = __webpack_require__(1);
var ReactDOM = __webpack_require__(2);
var Hello_1 = __webpack_require__(3);
ReactDOM.render(React.createElement(Hello_1.Hello, {compiler: "TypeScript", framework: "React"}), document.getElementById("example"));
/***/ },
/* 1 */
/***/ function(module, exports) {
module.exports = React;
/***/ },
/* 2 */
/***/ function(module, exports) {
module.exports = ReactDOM;
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var React = __webpack_require__(1);
var Hello = (function (_super) {
__extends(Hello, _super);
function Hello() {
_super.apply(this, arguments);
}
Hello.prototype.render = function () {
return React.createElement("h1", null,
"Hello from ",
this.props.compiler,
" and ",
this.props.framework,
"!");
};
return Hello;
}(React.Component));
exports.Hello = Hello;
/***/ }
/******/ ]);
//# sourceMappingURL=bundle.js.map
也会生成指定的sourceMap文件。
如果运行:
webpack-dev-server --inline
可以通过访问localhost:8080来访问这个工程。并且支持冷刷新,也就是更新一个文件之后,会刷新整个项目的所有内容,也可以通过修改webpack的配置来支持热刷新,只更新其中对应模块的代码。
其他有关webpack的内容具体可以参考webpack官方的参考文档。