基于webpack4.X从零搭建React脚手架的方法步骤


Posted in Javascript onDecember 23, 2018

项目初始化

$ npm init

安装webpack

本次创建是基于webpack4

$ npm install --save-dev

新建webpack配置文件

在根目录创建build文件夹,添加一个js文件,命名为webpack.base.conf.js

// webpack.base.conf.js 文件
const path = require('path');
const DIST_PATH = path.resolve(__dirname, '../dist');
module.exports = {
    entry: {
      app: './app/index.js'
    },
    output: {
      filename: "js/bundle.js",
      path: DIST_PATH
    }
};

使用merge的方式来组织webpack基础配置和不同环境的配置

先安装webpack-merge:

$ npm install --save-dev webpack-merge

在build文件夹中再添加一个js文件,命名为 webpack.prod.conf.js

// webpack.prod.conf.js 文件
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
module.exports = merge(baseWebpackConfig, {
  mode: 'production'
});

在根目录下创建app目录,然后创建index.js文件

var element =document.getElementById('root');
element.innerHTML = 'hello, world!';

在根目录创建一个public文件夹,然后新建一个index.html文件

// index.html
<!DOCTYPE html>
<html lang="en">
 <head>
   <meta charset="UTF-8">
   <title>从零开始搭建react工程</title>
 </head>
 <body>
    <div id="root"></div>
    <script src="../dist/js/bundle.js"></script>
 </body>
</html>

当前项目目录树

|- /app
  |- index.js
 |- /node_modules
 |- /public
  |- index.html
 |- /build
  |- webpack.base.conf.js
  |- webpack.prod.conf.js
 |- package.json
 |- package-lock.json

安装webpack-cli

webpack 4.0 版本之后的webpack,已经将webpack命令工具迁移到webpack-cli模块了,需要安装 webpack-cli

$ npm install --save-dev webpack-cli

package.json文件 scripts属性配置一个build命令

其值为:webpack --config build/webpack.prod.conf.js,以下是scripts的相关代码

// package.json
"scripts": {
  "build": "webpack --config build/webpack.prod.conf.js",
  "test": "echo \"Error: no test specified\" && exit 1"
},

安装React

$ npm install --save react react-dom

修改app目录下的index.js的代码

import React from "react";
import ReactDom from "react-dom";

ReactDom.render(
  <h1>hello, world!</h1>,
  document.getElementById("root")
);

注意 import 属于ES6规范,因此需要转译ES2015+的语法,安装并配置 babel 以及相关依赖

$ npm install --save-dev babel-loader babel-core babel-preset-env babel-preset-react

根目录创建.babelrc文件,配置presets.

{
 "presets": [
  [
   "env",
   {
    "targets": {
     "browsers": [
      "> 1%",
      "last 5 versions",
      "ie >= 8"
     ]
    }
   }
  ],
  "react"
 ]
}

修改webpack.base.conf.js文件

// webpack.base.conf.js
const path = require('path');
const APP_PATH = path.resolve(__dirname, '../app');
const DIST_PATH = path.resolve(__dirname, '../dist');
module.exports = {
  entry: {
    app: './app/index.js'
  },  
  output: {
    filename: 'js/bundle.js',
    path: DIST_PATH
  },
  module: {
    rules: [
      {
        test: /\.js?$/,
        use: "babel-loader",
        include: APP_PATH
      }
    ]
  }
};

运行 npm run build

添加插件

public下的index.html本该自动添加到dist目录,并且引用资源自动加载到该文件,通过html-webpack-plugin实现这一步

$ npm install html-webpack-plugin --save-dev

webpack.prod.conf.js中配置plugins属性

const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = merge(baseWebpackConfig, {
  mode: 'production',
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      inject: 'body',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
    })
  ]
});

删除 index.html 中手动引入的 script 标签

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>从零开始搭建react工程</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

重新编译查看 npm run build 浏览器打开查看目录 dist 下的 index.html

以上步骤都成功的前提下继续走下一步

生成的文件名添加Hash值,目的是解决缓存问题

修改webpack.prod.conf.js,mode: 'production', 增加以下代码

// webpack.prod.conf.js
output: {
  filename: "js/[name].[chunkhash:16].js",
},

生成前需要清理之前项目生成的文件,因为由于文件名的改变如果不删除会一直增加

安装插件 clean-webpack-plugin

$ npm install --save-dev clean-webpack-plugin

修改 webpack.prod.conf.js

// webpack.prod.conf.js
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = merge(baseWebpackConfig, {
  mode: 'production',
  output: {
    filename: "js/[name].[chunkhash:16].js",
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      inject: 'body',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
    }),
    new CleanWebpackPlugin(['../dist'], { allowExternal: true })
  ]
});

公共代码与业务代码分离

修改 webpack.base.conf.js 的 entry 入口属性,抽出框架代码

entry: {
   app: './app/index.js',
   framework: ['react','react-dom'],
},

修改webpack.prod.conf.js,增加以下代码,目的是分离框架代码和业务代码

虽然上面步骤抽出框架代码生成两个文件,但是app.js还是包含框架代码

optimization: {
    splitChunks: {
      chunks: "all",
      minChunks: 1,
      minSize: 0,
      cacheGroups: {
        framework: {
          test: "framework",
          name: "framework",
          enforce: true
        }
      }
    }
  }

cacheGroups对象,定义了需要被抽离的模块

其中test属性是比较关键的一个值,他可以是一个字符串,也可以是正则表达式,还可以是函数。如果定义的是字符串,会匹配入口模块名称,会从其他模块中把包含这个模块的抽离出来

name是抽离后生成的名字,和入口文件模块名称相同,这样抽离出来的新生成的framework模块会覆盖被抽离的framework模块

整合 webpack-dev-server

开发环境开启服务监听文件改动实时更新最新内容

$ npm install --save-dev webpack-dev-server

在build中添加webpack.dev.conf.js文件

const path = require('path');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

module.exports = merge(baseWebpackConfig, {
  mode: 'development',
  output: {
    filename: "js/[name].[hash:16].js",
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      inject: 'body',
      minify: {
        html5: true
      },
      hash: false
    }),
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer: {
    port: '8080',
    contentBase: path.join(__dirname, '../public'),
    compress: true,
    historyApiFallback: true,
    hot: true,
    https: false,
    noInfo: true,
    open: true,
    proxy: {}
  }
});

在package.json scripts属性添加内容

"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",

npm run dev

自动打开浏览器打开入口页面实时更新

独立导出 css 文件

安装css相关依赖

sass less 预处理

$ npm install extract-text-webpack-plugin
$ npm install style-loader css-loader postcss-loader autoprefixer --save-dev
$ npm install less sass less-loader sass-loader stylus-loader node-sass --save-dev

webpack.base.conf.js 文件修改

// webpack.base.conf.js
{
  test: /\.css$/,
  use: [
    {
     loader: "style-loader" //在html中插入<style>标签
     },
     {
       loader: "css-loader",//获取引用资源,如@import,url()
     },
     {
       loader: "postcss-loader",
       options: {
          plugins:[
            require('autoprefixer')({
              browsers:['last 5 version']
            })
         ]
       }
    }
   ]
},
{
  test:/\.less$/,
  use: [
     { loader: "style-loader" },
     { loader: "css-loader" },
     {
      loader: "postcss-loader",//自动加前缀
      options: {
          plugins:[
             require('autoprefixer')({
               browsers:['last 5 version']
             })
         ]
      }
     },
     { loader: "less-loader" }
   ]
},
{
   test:/\.scss$/,
   use:[
       { loader: "style-loader" },
       {
           loader: "css-loader",
       },
       { loader: "sass-loader" },
       {
        loader: "postcss-loader",
       options: {
          plugins:[
             require('autoprefixer')({
              browsers:['last 5 version']
             })
          ]
       }
     }
   ]
},

图片和路径处理

$ npm i file-loader url-loader --save-dev

webpack.base.conf.js 文件修改

// webpack.base.conf.js
{
  test: /\.(png|jpg|gif|woff|svg|eot|woff2|tff)$/,
  use: 'url-loader?limit=8129', 
  //注意后面那个limit的参数,当你图片大小小于这个限制的时候,会自动启用base64编码图片
  exclude: /node_modules/
}

build 时报错

Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
    at Chunk.get (F:\react\createApp\node_modules\webpack\lib\Chunk.js:824:9)

webpack4.0中使用“extract-text-webpack-plugin”报错

解决办法

$ npm install extract-text-webpack-plugin@next

背景图片路径问题

由于css文件分离出来的原因,会导致在css文件夹下找images文件夹下的图片

解决办法 publicPath属性改为 '/',以绝对路径的方式寻找资源

{
  test:/\.(png|jpg|gif)$/,
  use:[{
    loader:'url-loader',
    options: {
       // outputPath:'../',//输出**文件夹
       publicPath: '/',
       name: "images/[name].[ext]",
       limit:500 //是把小于500B的文件打成Base64的格式,写入JS
     }
   }]
},

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
兼容多浏览器的字幕特效Marquee的通用js类
Jul 20 Javascript
三级下拉菜单的js实现代码
May 23 Javascript
用js判断页面刷新或关闭的方法(onbeforeunload与onunload事件)
Jun 22 Javascript
基于jQuery实现下拉收缩(展开与折叠)特效
Dec 25 Javascript
JavaScript将一个数组插入到另一个数组的方法
Mar 19 Javascript
微信小程序城市定位的实现实例(获取当前所在国家城市信息)
May 17 Javascript
jQuery实现页码跳转式动态数据分页
Dec 31 jQuery
Vue 中使用vue2-highcharts实现曲线数据展示的方法
Mar 05 Javascript
Intellij IDEA搭建vue-cli项目的方法步骤
Oct 20 Javascript
vue获取时间戳转换为日期格式代码实例
Apr 17 Javascript
javascript中undefined的本质解析
Jul 31 Javascript
小程序两种滚动公告栏的实现方法
Sep 17 Javascript
JavaScript基于数组实现的栈与队列操作示例
Dec 22 #Javascript
jQuery实现侧边栏隐藏与显示的方法详解
Dec 22 #jQuery
JavaScript时间日期操作实例小结【5个示例】
Dec 22 #Javascript
JavaScript文本特效实例小结【3个示例】
Dec 22 #Javascript
JavaScript实现的鼠标跟随特效示例【2则实例】
Dec 22 #Javascript
iview实现select tree树形下拉框的示例代码
Dec 21 #Javascript
Element input树型下拉框的实现代码
Dec 21 #Javascript
You might like
基于qmail的完整WEBMAIL解决方案安装详解
2006/10/09 PHP
通过table标签,PHP输出EXCEL的实现方法
2013/07/24 PHP
PHP实现发送邮件的方法(基于简单邮件发送类)
2015/12/17 PHP
php采用session实现防止页面重复刷新
2015/12/24 PHP
PHP模拟http请求的方法详解
2016/11/09 PHP
PHP封装返回Ajax字符串和JSON数组的方法
2017/02/17 PHP
Laravel中log无法写入问题的解决
2017/06/17 PHP
FLASH 广告之外的链接
2008/12/16 Javascript
鼠标移到导航当前位置的LI变色处于选中状态
2013/08/23 Javascript
javascript获取浏览器类型和版本的方法(js获取浏览器版本)
2014/03/13 Javascript
javascript中异常处理案例(推荐)
2016/10/03 Javascript
JS绘制微信小程序画布时钟
2016/12/24 Javascript
封装运动框架实战左右与上下滑动的焦点轮播图(实例)
2017/10/17 Javascript
bootstrap table表格插件之服务器端分页实例代码
2018/09/12 Javascript
在Vue项目中使用snapshot测试的具体使用
2019/04/16 Javascript
vue 框架下自定义滚动条(easyscroll)实现方法
2019/08/29 Javascript
JavaScript 作用域scope简单汇总
2019/10/23 Javascript
JavaScript实现图片放大预览效果
2020/11/02 Javascript
[01:13:17]Secret vs NB 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[02:40]2018年度DOTA2最佳新人-完美盛典
2018/12/16 DOTA
Python聊天室实例程序分享
2016/01/05 Python
linux平台使用Python制作BT种子并获取BT种子信息的方法
2017/01/20 Python
Python处理中文标点符号大集合
2018/05/14 Python
python常用函数与用法示例
2019/07/02 Python
python3 自动识别usb连接状态,即对usb重连的判断方法
2019/07/03 Python
Python实现播放和录制声音的功能
2020/08/12 Python
scrapy-redis分布式爬虫的搭建过程(理论篇)
2020/09/29 Python
纯CSS3实现带动画效果导航菜单无需js
2013/09/27 HTML / CSS
捷克移动配件网上商店:ProMobily.cz
2019/03/15 全球购物
电大物流学生的自我评价
2013/10/25 职场文书
高三毕业生自我鉴定
2013/12/20 职场文书
高等教育专业自荐信范文
2014/03/26 职场文书
廉政承诺书
2015/01/19 职场文书
关于五一放假的通知
2015/08/18 职场文书
关于Python OS模块常用文件/目录函数详解
2021/07/01 Python
动画「半妖的夜叉姬」新BD特典图公开
2022/03/22 日漫