刚入门React时经常直接使用官方的脚手架进行开发,最近学习了webpack之后,自己决定从0开始搭建一个可以简单运行的React项目。
(1)在新建的文件夹下执行npm init命令,运行构建新项目的向导。以下代码是package.json文件中初始化的代码。
{
"name": "react",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
(2)我们需要在代码中安装webpack和webpack-cli,我们安装的webpack-cli这个包是让我们可以正确的在命令行中运行webpack这个命令,假设不安装这个包,就无法在命令行中运行webpack这个命令了。运行命令npm install webpack webpack-cli -D。
(3)接下来我们需要创建webpack的配置文件,然后进行简单的配置。
const path=require('path');
module.exports={
mode:'development',
entry:{
main:'./src/index.js'
},
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist')
}
}
以上对webpack打包的入口和打包出口进行了简单的配置,现在这个配置文件可以用来简单打包js文件,但是对于css无法打包。css的打包需要额外安装一些loader。
(4)安装css文件打包所需的loader,分别是css-loader,style-loader,postcss-loader,这三个loader的作用在下面会详细介绍。执行npm install ,然后配置css文件。与postcss-loader配套使用的还有npm install css-loader style-loader postcss-loader autoprefixer -D。细心的朋友可能会发现命令中还有一个叫做antoprefixer的插件, 这个插件是配合postcss-loader使用的,这样就可以自动为样式添加厂商前缀了。
上文中已经提到的loader和plugin这两个webpack中的两个核心概念。
loader的作用:webpack自身只支持js和json这两种格式的文件,对于其他文件需要通过loader将其转换为commonJS规范的文件后,webpack才能解析到。
plugin的作用:是用于在webpack打包编译过程里,在对应的事件节点里执行自定义操作,比如资源管理、bundle文件优化等操作。
如果从自己手写一个loader和plugin的角度来分析的话,loader是一个函数,plugin是一个类。plugin的编写比loader更复杂,webpack的源码中80%的代码都是基于plugin的机制编写的,plugin是webpack的灵魂。
然后我们分别介绍一下这三个loader的作用:
- style-loader:style-loader是把 js 中导入的样式文件代码,打包到 js 文件中,运行 js 文件时,动态创建style标签,并将样式自动插入到页面的header部分。
- css-loader:css-loader会分析出多个css文件之间的关系,官方解释是css-loader 解释@import 和 url() ,会 import/require() 后再解析(resolve)它们。
- postcss-loader负责将css文件解析成js文件可以操作的抽象语法树,然后再使用其它插件就能处理解析后的css文件了,例如使用autoPrefixer插件就可以为css样式加一些厂商前缀。这个loader一般需要与其它插件配合使用,而且可以单独为这个插件建一个配置文件postcss.config.plugin。
前面将了很多概念相关的内容,接下来就看看webpack的配置文件中怎么配置这些loader。
const path=require('path');
module.exports={
mode:'development',
entry:{
main:'./src/index.js'
},
module:{
rules:[{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test:/\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
]
}
]
},
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist')
}
}
接下来是postcss.config.js中的配置,这里配置的是autoprefixer插件,为样式代码增加厂商前缀,防止部分浏览器对书写的css不兼容。
module.exports={
plugins:[
require('autoprefixer')
]
}
(5)接下来就可以安装webpack-dev-server了,它可以帮助我们在代码保存之后会自动帮我们刷新页面,而且启动项目时会自动帮我们打开网页。命令行输入:npm install webpack-dev-server -D。 然后在webpack的配置文件中对这个插件进行配置。
const path=require('path');
const HtmlWebpackPlugins=require('html-webpack-plugin');
module.exports={
mode:'development',
entry:{
main:'./src/index.js'
},
devServer:{
contentBase:'./dist',
open:true,
port:8000
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
]
}
]
},
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist')
}
}
还需要在package.json文件中修改scripts
"scripts": {
"start": "webpack-dev-server"
},
(6)我们还需要安装一个插件HtmlWebpackPlugin,HtmlWebpackPlugin会在打包结束后自动生成一个html文件,并把打包生成的js自动引入到这个html文件中,这个html是以我们事先写好的一个html文件为模板创建的。运行:npm install html-webpack-plugin -D。
const path=require('path');
const HtmlWebpackPlugins=require('html-webpack-plugin');
module.exports={
mode:'development',
entry:{
main:'./src/index.js'
},
devServer:{
contentBase:'./dist',
open:true,
port:8000
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
]
}
]
},
plugins:[new HtmlWebpackPlugins({
template:'src/index.html'
})
],
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist')
}
}
(7)安装babel相关的插件,运行命令行:npm install babel-loader @babel/core @babel/preset-env @babel/polyfill @babel/preset-react -D,然后修改webpack配置文件,对option的配置单独用.babelrc来写。
const path=require('path');
const HtmlWebpackPlugins=require('html-webpack-plugin');
module.exports={
mode:'development',
devtool:'cheap-module-eval-source-map',
entry:{
main:'./src/index.js'
},
devServer:{
contentBase:'./dist',
open:true,
port:8000
},
module:{
rules:[{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test:/\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
]
}
]
},
plugins:[new HtmlWebpackPlugins({
template:'src/index.html'
})
],
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist')
}
}
(8)安装React的两个核心包npm install react react-dom -D。 这样就搭建好了一个简单React脚手架,但是很多功能这个脚手架还需要额外配置,例如还需要配置url-loader,file-loader等。还需要配置一些用来做代码分割的插件,例如splitChunkPlugin,还有合并和压缩css文件的插件,还需要配置sourceMap等等。