npm init // 新建一个package.json文件
npm i -D webpack webpack-cli webpack-dev-server // 安装webpack相关
npm i --save react react-dom // 安装react
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react // 安装babel相关
npm i -D html-webpack-plugin // 生成html文件
复制代码
这里简单介绍一下babelhtml
babel-loadervue
babel的编译器,提供转码API,好比transform,babel-loader会直接调用babel-core API对文件进行转码。node
@babel/corereact
文件转码器,简单的说就是将es6 es7转换为让浏览器识别es5。webpack
这里面包括了babel 的核心 api,好比 transform,主要都是处理转码的。它会把咱们的 js 代码,抽象成 ast,即 abstract syntax tree(抽象语法树) 的缩写,是源代码的抽象语法结构的树状表现形式。咱们能够理解为,它定义的一种分析 js 语法的树状结构。也就是说 es6 的新语法,跟老语法是不同的,那咱们怎么去定义这个语法呢。因此必需要先转成 ast,去发现这个语法的 kind,分别作对应的处理,才能转化成 es5.es6
@babel/preset-envweb
能够根据配置的目标运行环境自动启用须要的babel插件,例如对支持的浏览器进行配置:ajax
{
"targets": {
"chrome": "58",
"ie": "11"
}
}
复制代码
能够在.babelrc文件对babel进行配置。 更多须要了解babel的请点击这里。chrome
webpack.dev.conf.jsnpm
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 生成html模板
const resolve = (dir) => path.join(__dirname, '..', dir);
module.exports = {
mode: 'development', // webpack4新增属性,默认返回production,提供一些默认配置,例如cache:true
devtool: 'cheap-module-eval-source-map',
// source-map每一个module生成对应的map文件
// eval 每个module模块执行eval,不生成map文件,在尾部生成一个sourceURL对应先后关系,因此更快
// cheap 列信息 VLQ编码
// module 包含了模块之间的sourcemap
entry: {
home: './src/index.js', // 设置入口文件
},
output: {
filename: '[name].js', // 生成的js文件的名字
path: resolve('dist'), // 生成的js存放目录
},
module: { // 配置loader
rules: [
{
test: /\.m?js$/,
include: resolve('src'), // 只解析src下面的文件,不推荐用exclude
use: {
loader: 'babel-loader',
}
},
],
},
devServer: { // 配置webpack-dev-server, 在本地启动一个服务器运行
host: 'localhost', // 服务器的ip地址 但愿服务器外能够访问就设置 0.0.0.0
port: 8088, // 端口
open: true, // 自动打开页面
},
plugins: [
new HtmlWebpackPlugin({
filename: resolve('/dist/index.html'), // 生成的html文件存放的地址和文件名
template: resolve("/index.html"), // 基于index.html模板进行生成html文件
}),
]
}
复制代码
index.js
import ReactDOM from 'react-dom';
import React from 'react';
ReactDOM.render(
<h1>表白任素汐!</h1>,
document.getElementById('root')
)
复制代码
.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
]
}
复制代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Webpack Sample Project</title>
</head>
<body>
<div id='root'>
</div>
</body>
</html>
复制代码
在package.json的scripts添加命令
"dev": "webpack-dev-server --config build/webpack.dev.conf.js",
复制代码
最后在命令行启动,一个最简单的react项目配置好了。
npm run dev
复制代码
webpack经过watch实现热更新,其实就是将咱们最后一次修改的时间记录下来,而后定时去监测咱们文件的修改时间,发现二者不同,webpack就会本身去从新建立,咱们能够设置监测的间隔时间,以及发现了不一样,延长多久去从新构建。(详见webpack WatchOptions)
若是改变页面内容,整个页面都会刷新,可是若是模块不少的话,编译就会很慢。模块热更新就是检测代码有没有修改,只将修改的模块进行从新编译,并替换掉以前的模块,这样只有改变的模块才会更新,就像ajax同样局部刷新。
npm install react-hot-loader
npm i -D @babel/plugin-proposal-class-properties // 这个是针对es6 class进行添加的,由于咱们新建了home.js文件用了class
复制代码
修改webpack.dev.conf.js
devServer: {
hot: true, // 设置热更新(引用react热更新必须设置)
},
plugins: [
new webpack.HotModuleReplacementPlugin(), // 引入热更新插件(引用react热更新必须设置),
]
复制代码
.babelrc修改成
{
"presets": [
"@babel/preset-react",
"@babel/preset-env"
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"react-hot-loader/babel"
]
}
复制代码
新建一个home.js
import React, { Component } from 'react';
import { hot } from 'react-hot-loader';
class App extends Component {
state = { }
render() {
return (
<h1>表白任素汐!</h1>
);
}
}
export default hot(module)(App);
复制代码
修改index.js
import ReactDOM from 'react-dom';
import React from 'react';
import App from './home';
ReactDOM.render(
<App />,
document.getElementById('root')
)
复制代码
npm run dev看看效果吧~
随着项目愈来愈大,咱们开发调试的时候,最但愿的是节省时间,尽量快的进行编译。dllplugin借鉴于windows的dll文件,咱们能够把一些项目不会改动的存放在一个文件中,每次webpack进行从新编译的时候,咱们就能够直接加载,而不用再进行从新编译,就像react,react-dom等项目包。
按照这个思路咱们咱们再添加一个webpack.dll.config.js文件
const path = require('path')
const webpack = require('webpack')
// 生产环境不用dll的缘由是由于不少相同的内容会重复打包的bundles里面
module.exports = {
entry: {
vendor: ['react', 'react-dom']
},
output: {
path: path.join(__dirname, '..', 'dist/vendor'),
filename: '[name].dll.js',
library: '[name]_[hash]'
// vendor.dll.js中暴露出的全局变量名。
// 主要是给DllPlugin中的name使用,
// 故这里须要和webpack.DllPlugin中的name,保持一致。
},
//在给定的 path 路径下建立一个名为 manifest.json 的文件。 这个文件包含了从 require 和 import 的request到模块 id 的映射。 DLLReferencePlugin 也会用到这个文件。
plugins: [
new webpack.DllPlugin({
context: __dirname,
// 定义打包的公共vendor文件对外暴露的函数名
name: '[name]_[hash]',
// manifest.json文件的输出位置
path: path.join(__dirname, '..', 'dist/vendor/manifest.json')
})
]
}
复制代码
webpack.dev.conf.js添加
devServer: {
contentBase: resolve('dist'), // 设置服务器从那个目录提供内容,默认当前 推荐使用绝对路径。
},
plugins: [
new HtmlWebpackPlugin({
filename: resolve('/dist/index.html'), // 生成的html文件存放的地址和文件名
template: resolve("/index.html"), // 基于index.html模板进行生成html文件
vendor: './vendor/vendor.dll.js',
}),
new webpack.DllReferencePlugin({
context: __dirname, // 跟dll.config里面DllPlugin的context一致
manifest: require(path.join(__dirname, '..', 'dist', '/vendor/manifest.json')),
}),
],
复制代码
在配置dllplugin的时候,有几个坑务必要注意!!!
<script src="<%= htmlWebpackPlugin.options.vendor %>"></script>
复制代码
咱们在package.json的scripts中添加命令行:
"dev_dll": "webpack --config build/webpack.dll.config.js",
复制代码
执行dev_dll就能够在看到打包好的vendor.dll.js文件
npm run dev_dll
复制代码
咱们再执行npm run dev,咱们能够看到delegated ... from dll-reference的打包引用,就说明了dllplugin引用成功了
[./node_modules/_react-dom@16.6.3@react-dom/index.js] delegated ../node_modules/_react-dom@16.6.3@react-dom/index.js from dll-reference vendor_3b82321a4a4ec9fad65d 42 bytes {home} [built]
复制代码
随着项目的丰富,咱们能够把更多的不改动的三方包放在vendor.dll.js中,预计能够给项目带来30—40%的速度提高!
写在最后,dllplugin追求的是开发调试的时候尽量减小webpack编译的时间,官方不推荐放在production中使用,一方面是dllplugin会打包重复代码(好比在vue项目中elementui,dllplugin会重复打包vue),这个也许能够进行一些优化,可是生产环境咱们追求再也不是时间,而是文件体积和加载速度等,感兴趣的童鞋能够本身研究一下~