Webpack 系列之手把手教你使用 Webpack 搭建简易的 React 开发环境

发布于 2022-10-09 17:26:07 字数 14107 浏览 160 评论 0

在这篇文章中我们开始利用我们之前所学搭建一个简易的React开发环境,用以巩固我们之前学习的Webpack知识。首先我们需要明确这次开发环境需要达到的效果:

  • 能够编译 JSX 语言
  • css 样式使用 Sass 开发
  • 能够将基础的 ES6 转化为 ES5
  • 能够使用 ESLint 在开发的时候为我们做代码风格审查

首先,安装基本使用的 webpack、webpack-dev-server

npm i webpack webpack-dev-server -D

基本页面的生成

为了可以生成一个基本的页面我们使用 html-webpack-plugin,为了方便我们定制,我们自己在 src 定义一个 html 文件,使用 template 指定这个文件。

安装 html-webpack-plugin

npm i html-webpack-plugin -D

在 src 文件夹下生成一个 html 文件,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div></div>
</body>
</html>

在 webpack.config.js 中写入以下内容作为基本的设置:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const config = {
  entry: './src/main.js',
  output: {
    filename: 'bundle-[hash].js',
    path: path.join(__dirname, 'dist')
  },
  devtool:'inline-source-map',
  devServer: {
    contentBase: './dist',
    hot: true
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.HotModuleReplacementPlugin()
  ]
}

module.exports = config;

此时在命令行中运行以下命令可以看到一切正常运行,尽管目前在浏览器上还没有任何效果:

webpack-dev-server --open

编译 es6 和 jsx 语言

在 React 开发的时候我们使用 jsx 语言和 es6,因此需要使用 babel 对我们的开发进行一个编译,使用 babel 即可:
安装 babel-loader:

npm i babel-loader -D

为了使用这个 babel-loader,我们需要安装 babel-core(当我们需要以编程方式使用 babel 时就需要安装这个):

npm i babel-core -D

为了编译 es6 和 jsx 需要安装相应的 preset,即需要安装 babel-preset-react 和 babel-preset-es2015:

npm i babel-preset-es2015 babel-preset-react -D

在 webpack 的配置文件中引入 babel-loader:

const config = {
  //....
  module:{
    rules: [
      {
        test: /.(js|jsx)$/,
        use:[
          'babel-loader'
        ]
      }
    ]
  }
  // ......
}

module.exports = config;

配置 babel 的配置文件,在 .babelrc 文件中写入以下内容:

{
  "presets": [
    "es2015",
    "react"
  ]
}

此时我们测试一下是否可以正常编译 jsx 和 es2015,安装 react 和 react-dom,同时在 src 中的 main.js 和 App.js 写入部分内容

npm i react react-dom -S

main.js

import ReactDOM from 'react-dom';
import React from 'react';
import App from './App';

ReactDOM.render(<App />, document.getElementById('app'));

App.js

import React from 'react';

export default function () {
  return (
    <div className="header">
      React
    </div>
  );
}

在命令行运行命令,可以发现浏览器已经正常显示了,也就是说正常编译了 jsx 和 es6

webpack-dev-server --open

此时,整个 webpack.config.js 文件内容如下:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const config = {
  entry: './src/main.js',
  output: {
    filename: 'bundle-[hash].js',
    path: path.join(__dirname, 'dist')
  },
  devtool:'inline-source-map',
  devServer: {
    contentBase: './dist',
    hot: true
  },
  module: {
    rules: [
      {
        test: /.(js|jsx)/,
        use:[
          'babel-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      title:'React简易开发环境',
      template: './src/index.html'
    }),
    new webpack.HotModuleReplacementPlugin()
  ]
}

module.exports = config;

编译 Sass 样式

编译 Sass 和之前文章提到的一样,需要使用 style-loader、css-loader、sass-loader,首先进行安装:

npm i style-loader css-loader sass-loader -D

因为 sass-loader 是依赖 node-sass 的,同时因为 sass-loade r的 uri 是相对于 output 的,因此需要使用 resolve-url-loader

npm i node-sass resolve-url-loader -D

在 webpack.config.js 中进行配置:

const config = {
  // ......
  module: {
    rules: [
      //......
      {
        test: /.(sass|scss|css)/,
        use: [
        "style-loader",
        "css-loader",
        "resolve-url-loader",
        "sass-loader?sourceMap"
        ]
      }
    ]
  },
  // ......
}

module.exports = config;

在 src 文件夹中新建一个名为 sass 的文件夹,同时新建 _header.scss、_variablers.scss、main.scss,三个文件内容分别为:

_variablers.scss

$bgColor: red;
$fontColor: #fff;

_header.scss

.header{
	background: $bgColor;
	color: $fontColor;
	height:300px;
}

main.scss

@import "variables"
,"header"

在 main.js 中引入 main.scss 文件:

import './sass/main.scss';

此时再次运行命令,可以在浏览器中看到 header 部分的样式已经生效。

此时整个 webpack.config.js 文件内容如下:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const config = {
  entry: './src/main.js',
  output: {
    filename: 'bundle-[hash].js',
    path: path.join(__dirname, 'dist')
  },
  devtool:'inline-source-map',
  devServer: {
    contentBase: './dist',
    hot: true
  },
  module: {
    rules: [
      {
        test: /.(js|jsx)/,
        use:[
          'babel-loader'
        ]
      },{
        test: /.(sass|scss|css)/,
        use: [
        "style-loader",
        "css-loader",
        "resolve-url-loader",
        "sass-loader?sourceMap"
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      title:'React简易开发环境',
      template: './src/index.html'
    }),
    new webpack.HotModuleReplacementPlugin()
  ]
}

module.exports = config;

配置 ESLint 为我们做代码风格检查

使用 eslint 首先安装 eslint 和 eslint-loader:

npm i eslint eslint-loader -D

为了让 eslint 支持 es6 我们需要将 eslint 的解析器修改为 babel-eslint,使用 npm 安装

npm i babel-eslint -D

在 webpack.config.js 中配置 eslint-loader

const config = {
  // ......
  module: {
    rules: [
      {
        test: /.(js|jsx)/,
        use:[
          'babel-loader',
          'eslint-loader'
        ]
      }
    ]
  },
  // ......
}

module.exports = config;

新建一个 eslint 的配置文件 .eslintrc.js:

module.exports = {
  "parserOptions": {
    "ecmaVersion": 6,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "env": {
    "browser": true,
    "node": true
  },
  "parser": "babel-eslint"
};

此时运行命令行会发现正常运行,原因是 eslint 默认所有规则都是禁用的,我们在 .eslintrc.js 中添加一条简单的禁用 console 的规则,当出现 console 时,将会报 warning

module.exports = {
  "parserOptions": {
    "ecmaVersion": 6,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "env": {
    "browser": true,
    "node": true
  },
  "parser": "babel-eslint",
  "rules": {
  	"no-console": 1
  }
};

此时再次运行命令,可以发现以下界面,控制台已经很明确的告诉我们,我们的 App.js 中出现了 console,说明此时 eslint 已经生效。

console

但是在一个项目中我们如果配置每一个规则会显得非常麻烦,因此我们选择使用 airbnb 的规则,使用 npm 安装:

npm i eslint-config-airbnb -D

安装完成之后可以发现控制台告诉我们需要安装 eslint-plugin-jsx-a11y、eslint-plugin-import、eslint-plugin-react,同时安装时应该大于或者等于某个版本号:

airbnb

npm i eslint-plugin-jsx-a11y@5.1.1 eslint-plugin-import@2.7.0 eslint-plugin-react@7.1.0 -D

在 .eslintrc.js 文件中使用 extends 指定继承自 airbnb 的配置,如下:

module.exports = {
  "parserOptions": {
    "ecmaVersion": 6,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "extends": "airbnb",
  "env": {
    "browser": true,
    "node": true
  },
  "parser": "babel-eslint",
  "rules": {
  	"no-console": 1
  }
};

此时,再次运行命令之后可以发现,在命令行和控制台中都报出了我们的代码风格问题,如下:

airbnb2

airbnb中的所有规则我们可以根据我们的需要进行重写,我们注意到其中一条 error 如下:

JSX not allowed in files with extension '.js'      react/jsx-filename-extension

前面的为相应说明,后面的为规则,这条不允许我们在 .js 文件中书写 JSX 语言,后面为对应的规则,显然是 eslint-plugin-react 插件的规则,我们可以重写以允许我们在 .js 文件中书写 JSX,如下:

module.exports = {
  "parserOptions": {
    "ecmaVersion": 6,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "extends": "airbnb",
  "env": {
    "browser": true,
    "node": true
  },
  "parser": "babel-eslint",
  "rules": {
  	"no-console": 1,
  	"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }]
  }
};

再次运行可以发现这条 error 已经不存在了。

在项目中解析图片模块

在之前的文章中我们已经提到过了,我们可以使用file-loader来实现:

npm i file-loader -D

在 webpack.config.js 中配置:

const config = {
  // ......
  module: {
    rules: [
      {
        test: /.(png|jpg|svg|gif)/,
        use:[
          "file-loader"
        ]
      }
    ]
  },
  // ......
}

module.exports = config;

此时我们可以引入图片资源了。

支持更多的 ES6 方法

我们在使用 babel 的时候我们需要明确知道的一点是,babel 默认只是为我们转化语法层面上的东西(如箭头函数),并不会为我们去将一些方法进行转化为 es2015 的实现,也就是说如果我使用 Array.of 方法,如果浏览器不支持这个方法,及时按照上面的 babel 转化也是依旧没有办法运行的,我们可以在 App.js 中使用 Array.of 方法来测试一下,如下:

Array.of(1,2,3,4).forEach(function(item){
		console.log(item);
	});

我们这次使用 webpack 命令直接在 dist 文件夹中生成相应的文件,我们可以在 js 文件中找到以下内容:

qq 20170912020314

这就验证了上文的说法,因此我们需要使用 babel-polyfill
首先进行安装:

npm i install babel-polyfill -D

安装完成之后我们需要在 webpack 的入口中进行配置,将 webpack 的 entry 修改为以下内容:

entry: ['babel-polyfill','./src/main.js']

开发与生产环境分离

我们现在使用 webpack 命令为我们打包一下内容,我们会发现打包后的文件非常大,只有部分内容却打包之后有 3000+kb,这是不能用在生产环境上的,如下:

default

文件体积太大一个重要原因是 devtool 开启了 inline-source-map 方便我们定位 bug,同时代码没有压缩也是重要原因之一,因此我们需要将开发和生产环境分离,使用不同的 webpack 配置。

还记得我们系列之前介绍的 webpack-merge 吗?我们通过这个插件可以将公共的配置分离到一起。首先进行安装

npm i webpack-merge -D

新建一个名为 webpack.common.js 文件作为公共配置,写入以下内容:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const config = {
  entry: ['babel-polyfill','./src/main.js'],
  output: {
    filename: 'bundle-[hash].js',
    path: path.join(__dirname, 'dist')
  },
  plugins: [
    new HtmlWebpackPlugin({
      title:'React简易开发环境',
      template: './src/index.html'
    })
  ]
}

module.exports = config;

新建一个名为 webpack.dev.js 文件作为开发环境配置,写入以下内容:

const merge = require('webpack-merge');
const common = require('./webpack.common');
const webpack = require('webpack');

const config = merge(common, {
  devtool:'inline-source-map',
  devServer: {
    contentBase: './dist',
    hot: true
  },
  module: {
    rules: [
      {
        test: /.(js|jsx)/,
        use:[
          'babel-loader',
          'eslint-loader'
        ]
      },{
        test: /.(sass|scss|css)/,
        use: [
        "style-loader",
        "css-loader",
        "resolve-url-loader",
        "sass-loader?sourceMap"
        ]
      },{
        test: /.(png|jpg|svg|gif)/,
        use:[
          "file-loader"
        ]
      }
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
});

module.exports = config;

刚刚我们提到我们在开发环境中应该压缩混淆代码同时精简输出,因此需要使用 uglifyjs-webpack-plugin 插件,首先进行安装:

npm i uglifyjs-webpack-plugin -D

新建一个名为 webpack.prod.js 的文件作为生产环境配置,写入以下内容:

const merge = require('webpack-merge');
const common = require('./webpack.common');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

const config = merge(common, {
  devtool:false,
  module: {
    rules: [
      {
        test: /.(js|jsx)/,
        use:[
          'babel-loader'
        ]
      },{
        test: /.(sass|scss|css)/,
        use: [
        "style-loader",
        "css-loader",
        "resolve-url-loader",
        "sass-loader?sourceMap"
        ]
      },{
        test: /.(png|jpg|svg|gif)/,
        use:[
          "file-loader"
        ]
      }
    ]
  },
  plugins:[
    new UglifyJSPlugin()
  ]
});

module.exports = config;

因为在开发时我们需要使用的命令是

webpack-dev-server --open --config webpack.dev.js

而在生产中我们需要使用的命令是

webpack --config webpack.prod.js

为了精简我们在命令行中的输入我们将这些命令写在 package.json 中

"scripts": {
    "dev": "webpack-dev-server --open --colors --progress --inline --config webpack.dev.js",
    "build": "webpack --colors --progress --config webpack.prod.js"
  }

此时我们只要在命令行中输入 npm run dev 即可开启开发环境,使用 npm run build 即可自动生成用于生产环境的文件。

使用 clean-webpack-plugin

现在还有一个问题是我们修改文件之后再次使用 npm run build 命令则会出现多个 js 文件,这是因为我们使用了 hash 占位符,这个占位符可以保证用户访问网站时始终保持最新的js文件,因此我们使用 clean-webpack-plugin 帮助我们每次删除dist文件夹的内容

npm i clean-webpack-plugin -D

在 webpack.prod.js 中引用:

const merge = require('webpack-merge');
const common = require('./webpack.common');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const config = merge(common, {
  // ......
  plugins:[
    new CleanWebpackPlugin(['./dist']),
    new UglifyJSPlugin()
  ]
});

module.exports = config;

开发 src 目录划分

虽然目前一个简易的 React 开发环境已经搭建好了,但是还是需要对 src 目录进行划分以保证良好的开发体验,以下是划分的目录:

└───Components
      └───......
      └───......
└───Containers
      └───......
      └───......
└───static
      └───sass
      └───img
└───index.html
└───main.js

目录功能相信一眼就能看出来了。这时一个简易的环境就已经搭建好了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

自在安然

暂无简介

0 文章
0 评论
25 人气
更多

推荐作者

qq_aHcEbj

文章 0 评论 0

寄与心

文章 0 评论 0

13545243122

文章 0 评论 0

流星番茄

文章 0 评论 0

春庭雪

文章 0 评论 0

潮男不是我

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文