使用 webpack4 从0开始搭建 react 项目

前言

最近在学习 webpack 基础使用,项目优化等问题。总感觉要写点东西记录一下。如果你对webpack感兴趣的话,可以跟着这篇文章来尝试搭建(大神自行略过),好了废话不多说直接进入正文。

一、项目搭建

初始化项目

mkdir react-webpack-demo
cd react-webpack-demo
npm init -y

安装 webpack,webpack4 将 webpack-cli 从 webpack 中分离了出来,所以这里要同时安装 webpack webpack-cli

npm i webpack webpack-cli -D

webpack 建议在局部安装,如果安装到全局,会锁定webpack版本,多项目使用 webpack 会因为版本问题导致项目构建失败

在 package.json 中增加运行命令

"scripts": {
    "dev": "webpack"
}

接下来在项目下创建 src 文件和 src/index.js 作为入口文件(webpack 默认配置中 entry 入口是 src/index.js)

执行 npm run dev 会看到在项目下会生成一个 dist 目录(打包成功)

到目前为止一个 webpack 项目已经搭建完成,下面将开始 webpack 配置以及搭建一个 react 项目

二、loader

首先在项目下创建 webpack.config.js,下文中会直接使用默认配置中的属性将不再全部展示。请读者自行根据属性进行辨别。

/**** webpack.config.js  ***/

// webpack 默认配置
const path = require('path');

module.exports = {
    // 项目入口文件 支持 str | [] | {}
    entry: path.resolve(__dirname, './src/index.js'),
    // 项目出口 
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'mian.js'
    },
    // 打包环境 默认是生产环境 production
    // 如果是开发环境 这里需要换成 development
    // 接下来为了观察打包后的文件,使用 development
    mode: 'development',
    // 模块 这些选项决定了如何处理项目中的不同类型的模块。
    module: {},
    // 插件
    plugins: [],
    // 是否开启 source-map
    devtool: 'cheap-module-eval-source-map'
}

webpack 默认只支持 js/json,可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。你可以使用 Node.js 来很简单地编写自己的 loader。

安装 style-loader/css-loader/file-loader

npm i css-loader style-loader file-loader -D
// webpack.config.js 
module: {
    rules: [
        {
            test: /\.css$/,
            use: [
                { loader: 'style-loader' },
                {
                    loader: 'css-loader',
                    options: {
                        modules: true
                    }
                },
            ]
        },
        {
            test: /\.(png|jpg|gif)$/,
            use: [
                {
                    loader: 'file-loader',
                    options: {},
                },
            ],
        }
    ]
},

ok 现在你可以随意打包css文件和图片资源了。

目前为止一切运行的都没有问题,我们尝试着在入口文件中写一些代码

const arr = [new Promise(() => { }), new Promise(() => { })];
arr.map(item => {
    console.log(item);
})

打包后查看文件


image

我们想要的效果是可以转换成 ES5 的代码来做浏览器兼容,OK开整。

这里使用babel来做代码转化

// 安装
npm i babel-loader @babel/core @babel/preset-env -D

// 在webpack.config.js中使用
module: {
    rules: [
        {
            test: /\.js/,
            loader: 'babel-loader'
        }
    ]
},

根目录下新建 .babelrc 文件来配 babel-loader 的配置项

// .babelrc
{
    "presets": ["@babel/preset-env"]
}

运行打包 npm run dev

image

到目前为止任务完成一半,Promise 等最新的特性还没有转换成功。

继续安装 @babel/polyfill 并在入口文件中引入

// 安装
npm i @babel/polyfill -D

// index.js
import '@babel/polyfill';

OK 现在编译成功了,生成的代码已经全部成功转成ES5的代码,但是

image

明明刚才才 几k 的代码,现在直接 400多k。原因是因为 webpack 会直接将 polyfill 中的方法全部打包到dist中去,可是明明我只使用了 Promise 这明显不是我想要的结果。

这里就需要配置 useBuiltIns 了

// 重新更改 .babelrc 文件
{
    "presets": [
        [
            "@babel/preset-env",
            {
                // 描述您为项目支持/目标的环境
                "targets": {
                    "browsers": ["> 1%", "last 2 versions"]
                },
                "corejs": 2, //新版本需要指定核⼼库版本
                // "usage"| "entry"| false,默认为false
                "useBuiltIns": "usage" //按需注⼊
            }
        ]
    ]
}

到目前为止webpack使用babel基础功能基本结束,更多 loader 请参考官方 https://www.webpackjs.com/loaders/

三、plugins

先看一波官方描述

webpack 有着丰富的插件接口(rich plugin interface)。webpack 自身的多数功能都使用这个插件接口。这个插件接口使 webpack 变得极其灵活。

上一步只是实现了打包css/js/图片资源打包的功能。下面我们将借助插件实现自动生成 html 文件。每次部署自动清空 dist 目录等基本功能

首先老套路,安装插件

npm i html-webpack-plugin clean-webpack-plugin -D

项目中使用,首先在项目下创建 index.html 模板

const htmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

plugins: [
    // 复制一个 html 并将最后打包好的资源在 html 中引入
    new htmlWebpackPlugin({
        // 页面title 需要搭配 ejs 使用
        title: "测试title",
        // html 模板路径
        template: "./index.html",
        // 输出文件名称
        filename: "index.html",
        minify: {
            // 压缩HTML⽂件
            removeComments: true, // 移除HTML中的注释
            collapseWhitespace: true, // 删除空⽩符与换⾏符
            minifyCSS: true // 压缩内联css
        }
    }),
    // 每次部署时清空 dist 目录
    new CleanWebpackPlugin()
],

开始搭建 react 项目

首先安装 react react-dom

npm i react react-dom -S

src 下重新创建 react.js 文件

import React, { Component } from 'react';
import ReactDom from 'react-dom';

class App extends Component {
    
    render() {
        return <div>
            hello word`12
        </div>
    }
}

// 需要在 index.html 中增加一个 div标签 id 设置为 'app'
ReactDom.render(<App />, document.getElementById('app'));

修改 webpack.config.js

entry: path.resolve(__dirname, './src/react.js'),
output: {
    path: path.resolve(__dirname, './dist'),
    // 模块标识符(module identifier)的 hash 取前8位
    filename: 'main_[hash:8].js'
},

在执行打包,会有一个报错,webpack 并不认识 react 的语法

image

安装 @babel/preset-react

npm i @babel/preset-react -D

在 .babelrc 中配置一下 @babel/preset-react


{
    "presets": [
        [
            "@babel/preset-env",
            {
                // 描述您为项目支持/目标的环境
                "targets": {
                  "browsers": ["> 1%", "last 2 versions"]
                },
                "corejs": 2, //新版本需要指定核⼼库版本
                "useBuiltIns": "usage" //按需注⼊
            }
        ],
        "@babel/preset-react"
    ]
}

OK 现在 react 项目就可以正常打包了。但是我们日常开发中并不会每次打完包再来看效果,这里的话就需要起一个服务并且配值热更新了。

首先我们需要安装 webpack-dev-server

npm i webpack-dev-server -D

配置 webpack.config.js 文件

const webpack = require('webpack')
module.exports = {
    // devServer和entry是平级的
    devServer: {
        // 指向打包后的文件地址
        contentBase: './dist',
        // 是否自动打开一个新窗口
        open: true,
        // 端口号
        port: 8081,
        // 是否开启热更新
        hot: true,
        // 启用热模块替换,而不会在构建失败时将页面刷新作为后备。
        hotOnly: true
    },
    plugins: [
        // 启用模块热替换(HMR - Hot Module Replacement)
        new webpack.HotModuleReplacementPlugin()
    ]
}

在package.json 中新增一条命令

"scripts": {
    "server": "webpack-dev-server"
}

到目前为止一个基础版的 react 就已经搭建完成了,下一篇分享将如何使用 webpack 优化项目。git 地址 https://github.com/shanyq1673/webpack-react

webpack 项目优化 请大家跳到 webpack 从0开始搭建 react(优化篇)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容