Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,而后将这些模块按照指定的规则生成对应的静态资源,它能够将多种静态资源 JavaScript、css、less 等转换成一个静态文件,减小了页面的请求。css
React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,它是一个用于构建用户界面的 JAVASCRIPT 库,主要用于构建UI,不少人认为 React 是 MVC 中的 V(视图)。因为拥有较高的性能,代码逻辑很是简单,因此在全球范围内的使用率都比较高。html
这一次为了更好的学习 webpack 环境的构建和开始 React 的开发,工程搭建将会以实现一个 todolist 为目标,将每个节点做为一个 commit,以便更直观的查看实现一个功能点所须要作的事情,同时也使得选择所需的依赖变得更简单可行。前端
你能够点击 show me the code 来查看和 Fork 此项目,若是你须要查看更多关于 Angular或Vue 开发环境的搭建能够点击 查看更多 来进行查看,欢迎你们一块儿学习和交流。node
$ mkdir webpack-react && cd webpack-react
$ yarn init
$ yarn init -y
$ yarn add webpack webpack-cli --dev
在 webpack 4 不是必需要有配置文件的,因此此时若是咱们在 index.js 中添加内容直接执行 webpack 就能够进行打包,由于在 webpack 4 中默认入口文件为 ./src/index.js,默认出口文件为 ./dist/main.js。react
安装完成以后咱们来对 webpack 进行简单的配置,首先咱们在 package.json 同级目录下建立 config 目录用于放置部分配置文件,如今咱们在 config 目录下新建 webpack.base.config.js 文件,用来存放开发模式和生产模式公共的配置文件,建立 webpack.dev.config.js 文件,用来存放开发模式下的配置文件,建立 webpack.build.config.js 文件,用来存放生产模式下的配置文件:webpack
$ mkdir config
$ cd config
$ touch webpack.base.config.js webpack.dev.config.js webpack.build.config.js
如今咱们先向共同的配置文件 webpack.base.config.js 中写入如下内容:git
const path = require('path');
module.exports = {
// 入口配置
entry: {
main: path.join(__dirname, '../src/index.js'),
},
// 输出配置
output: {
filename: 'js/[name].js', // 输出文件的文件名
path: path.join(__dirname, '../dist'), // 输出文件所在目录
}
};
如配置中所示,如今咱们去对应的目录下建立对应的入口文件 index.js,并在其中输出“Hello world”:github
// index.js
console.log('打包成功');
$ yarn add webpack-merge --dev
这里咱们先对开发模式下的配置文件进行配置:web
// 引入公共配置
const webpackBaseConfig = require('./webpack.base.config');
// 合并配置的插件
const webpackMerge = require('webpack-merge');
module.exports = webpackMerge(webpackBaseConfig, {
// 指定模式
mode: 'development',
// devtool由 webpack 直接提供,将打包后的文件中的错误映射到最初对应的文件中,便于调试
devtool: 'cheap-module-eval-source-map'
});
顺便咱们也把生产模式下也简单的配置一下,有时候咱们也能够打包一下,查看打包后文件存放的名称和路径等,以检测书写错误致使一些错误,固然如今咱们只须要对其进行简单的配置:npm
// 引入公共配置
const webpackBaseConfig = require('./webpack.base.config');
// 合并配置的插件
const webpackMerge = require('webpack-merge');
module.exports = webpackMerge(webpackBaseConfig, {
// 指定模式
mode: 'production'
});
$ yarn add webpack-dev-server --dev
因为它直接开发模式下会被用到,因此咱们直接去开发模式的配置文件(webpack.dev.config.js)下进行配置:
const path = require('path');
// 引入公共配置
const webpackBaseConfig = require('./webpack.base.config');
// 合并配置的插件
const webpackMerge = require('webpack-merge');
module.exports = webpackMerge(webpackBaseConfig, {
// 指定模式
mode: 'development',
// devtool由 webpack 直接提供,将打包后的文件中的错误映射到最初对应的文件中,便于调试
devtool: 'cheap-module-eval-source-map',
// 对 webpack-dev-server 进行配置
devServer: {
//本地服务器所加载的页面所在的目录
contentBase: path.join(__dirname, "../dist"),
/* 服务器的主机号,默认是 localhost
* 将该地址设为电脑的 ip 地址,局域网内的移动设备经过访问该地址下的30端口便可访问 web 应用
*/
host: 'localhost',
// 端口
port: 3000,
/* 设置编译后文件的路径,致使最后的文件文件地址为:http://localhost:3000/dist/index.js
*
* publicPath: 'http://localhost:3000/',
*/
/* 应对返回404页面时定向到特定页面
*
* historyApiFallback: {
* rewrites: [{
* from: /./,
* to: '/404.html'
* }]
* },
*/
// 热模块替换机制
//- hot: true,
/* 默认为 true, 意思是,在打包时会注入一段代码到最后的 js 文件中,用来监视页面的改动而自动刷新页面
* 当为 false 时,网页自动刷新的模式是 iframe,也就是将模板页放在一个 frame中
*
* inline: true,
*/
// 为 true 时,dev server 第一次会自动打开浏览器
open: true,
/* 对全部的服务器资源采用 gzip 压缩
* 对 JS,CSS 资源的压缩率很高,能够极大得提升文件传输的速率
* 可是须要服务端要对文件进行压缩,客户端进行解压,增长了两边的负载
*
* compress: true
*/
disableHostCheck: true
}
});
$ yarn add html-webpack-plugin html-loader --dev
由于该配置在两种模式下都须要使用,因此咱们在公共配置文件中进行配置:
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 入口配置
entry: {
main: path.join(__dirname, '../src/index.js'),
},
// 输出配置
output: {
filename: 'js/[name].js', // 输出文件的文件名
path: path.join(__dirname, '../dist'), // 输出文件所在目录
},
// 加载器
module: {
rules: [{
test: /\.html$/,
use: [{
loader: "html-loader",
options: {
minimize: true
}
}]
}]
},
// 插件管理
plugins: [
//建立 .html 并自动引入打包后的文件
new HTMLWebpackPlugin({
filename: 'index.html',
template: 'index.html',
// 参照最初建立的 .html 来生成 .html
inject: true,
// 引入根路径下的 favicon.ico
favicon: path.resolve('favicon.ico')
})
]
};
固然咱们在这里还须要在对应的目录下建立 index.html,也就是在根目录下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>webpack-react</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root">Hello world</div>
</body>
</html>
"scripts": {
"dev": "webpack-dev-server --config config/webpack.dev.config.js",
"build": "webpack --config config/webpack.prod.config.js"
}
Npm 中容许在 package.json 文件里面,使用 scripts 字段定义脚本命令。它是一个对象,它的每个属性,都对应一段脚本。
每当执行 npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令,新建的这个 Shell,会将当前目录的 node_modules/.bin 子目录加入 PATH 变量,执行结束后,再将 PATH变量恢复原样,因此当前目录的 node_modules/.bin 子目录里面的全部脚本,均可以直接用脚本名调用,而没必要加上路径。
由于咱们的配置文件不在根目录下,在这里咱们经过 --config 来指定执行脚本路径,如今咱们就可使用 npm run dev 开启 web 应用,若是前面的操做正确的化你将看到页面上显示“Hello world”的字样,而且控制台中输入“编译成功”的字样。
现在在前端开发中 Javascript 主要是用 ES6 编写的,但并非全部的浏览器都知道如何处理 ES6,所以咱们需对 ES6 进行转换。
在 webpack 的 loader(加载器)中,babel-loader 正是这样一个用于将 ES6 及以上版本转译至 ES5 的神器,要使用它咱们还须要安装一些依赖:
$ yarn add babel-loader @babel/core @babel/preset-env @babel/preset-react --dev
而后须要在公共配置文件中 rules 属性配置 babel-loader 的相关信息:
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
最后咱们须要在根目录下建立 .babelrc 文件写入如下内容:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
如今咱们就能够在项目中使用 ES6或着是JSX 语法啦。
首先咱们将根目录下 index.html 文件中的 "Hello world"文本删掉,而后在 ./src/index.js 文件中写入下面的内容:
import React from "react";
import ReactDOM from "react-dom";
const App = () => {
return (
<div>
<p>Hello world</p>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
显然保存后运行服务会报错,由于到目前位置咱们的项目还不支持 React、React-dom,为了进行 React 开发,首先咱们要安装以下依赖:
$ yarn add react react-dom
安装完成以后,再启动项目,会发现刚刚删除的 "Hello world"文本再次出现了,并且是经过 React 来实现的,到此 webpack-react 最基础的开发环境就搭建好了,可是 webpack 方面还有许多配置和一些须要优化的地方,因此咱们将在下篇文章里继续记录开发环境的搭建过程,你能够点击 搭建 webpack、react 开发环境(二) 来继续查看。