使用Webpack从0搭建React项目

222 阅读4分钟

刚入门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等等。