美文网首页
React项目模板-webpack解析

React项目模板-webpack解析

作者: stevekeol | 来源:发表于2019-05-04 19:05 被阅读0次

webpack到底是干什么的?

1. 分析得到所有必须模块并合并;
2. 提供了让这些模块有序、正常执行的环境;

webpack在项目中以什么方式存在?

先看一下最简单的react项目的文件结构:

项目文件树

需要理清以下问题/疑惑:

1. webpack跟package.json文件的关系;
2. webpack跟app文件夹的关系;
3. webpack跟.babelrc文件的关系;
4. webpack跟.eslintrc文件的关系;
5. webpack跟webpack.config.js文件的关系;
6. webpack跟webpack.prod.config.js文件的关系;
//1. webpack跟package.json文件的关系
【什么是package.json】Node.js中项目须遵循模块化的架构,模块的描述文件被称为package.json
【package.json中重要的配置项】: scripts、main、bin、devDependencies、dependencies
(1)scripts配置项: 简要的指明了运行脚本命令时(如 dev 指明 npm run dev)
                   所要执行的复杂命令(如 webpack-dev-server --hot --host 0.0.0.0);
(2)main配置项: 当该项目可用于导出一个功能模块时,配置main: index.js作为统一的入口文件;
                即可通过require('xxxName')而非require('xxxName/app/index.js');
(3)devDependencies配置项:开发过程中需要用到的依赖项;
(4)dependencies配置项: 最终产品中需要用到的依赖项;
(5)bin配置项:当该项目作为一个功能模块,希望以一个全局命令的形式调用时:    
              "bin": {
                  "rrg": "./bin/index.js"
              },
【package.json跟webpack的关系】:
    "scripts": {
      "build": "webpack -p --config webpack.prod.config.js",
      "dev": "webpack-dev-server --hot --host 0.0.0.0"
    }
    即执行脚本命令时,以webpack和响应的配置项来执行。
【命令' webpack -p --config webpack.prod.config.js' 详解】:
    -p 作用:(1)混淆压缩结果文件;
             (2)process.env.NODE_ENV="production", 即设置环境变量为production. 
【webpack.prod.config.js文件解析】:
      (详见下列源代码的注释)
// 2 .webpack跟app文件夹的关系
在webpack.prod.config.js 配置文件中  :
entry: {
    app: path.resolve(APP_PATH, 'app.jsx'), 
    vendor: ['react', 'react-dom', 'prop-types', 'marked', 'leancloud-storage']
  }
在entry.app处设置了业务逻辑的入口; APP_PATH即app文件夹。 
// 6 .webpack跟webpack.prod.config.js文件的关系
在执行脚本命令时,实际上是使用携带参数的webpack命令,
即使用--config webpack.prod.config.js 属性时表示,webpack按照配置文件进行构建。
//(webpack.prod.config.js 源码)
var path = require('path');
var webpack = require('webpack');
var HtmlwebpackPlugin = require('html-webpack-plugin'); //见下方解释@1
var ExtractTextPlugin = require("extract-text-webpack-plugin"); //见下方解释@2

var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'app'); //见下方解释@3
var BUILD_PATH = path.resolve(ROOT_PATH, 'build'); //见下方解释@4

module.exports= {
  entry: {
    app: path.resolve(APP_PATH, 'app.jsx'), //见下方解释@3
    vendor: ['react', 'react-dom', 'prop-types', 'marked', 'leancloud-storage']
  },
  output: {
    path: BUILD_PATH,
    filename: '[name].[hash].bundle.js' //见下方解释@4
  },
  resolve: { //指明webpack在该路径下去寻找依赖模块,Webpack 会自动带上后缀后去尝试访问文件是否存在
    modules: [APP_PATH, "node_modules"],
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/, //对APP_PATH路径下所有以.jsx/.js结尾的文件使用loaders转换代码
        loaders: ['babel-loader'],
        include: APP_PATH
      },
      {
        test: /\.s?css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader", //见解释@5
          use: ['css-loader', 'sass-loader']
        })
      }
    ]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({ //见解释@6
      name: "vendor"
    }),
    new ExtractTextPlugin("styles.css"), //见下方解释@2
    new HtmlwebpackPlugin({
      title: 'Deskmark app'
    })
  ]
}

//解释@1:(插件html-webpack-plugin的作用)
//自动生成项目的HTML文件


//解释@2:(插件extract-text-webpack-plugin的作用)
//默认情况下webpack在通过js引入css时,样式内容和js内容是一起加载的,
//样式内容的插入和解析甚至会被延后到js内容的执行期。可能会导致一个短暂的无样式瞬间。
//这与传统的前端页面性能优化方式(样式文件在<head>中就被加载,js延后至文档加载解析完才执行)相违背。
//借助插件ExtractTextPlugin,webpack可以在打包时将样式内容抽取出来
//并放在额外的css文件中,即此处的styles.css。
//在页面引入该styles.css文件即可。

//解释@3: (webpack入口设置)
//entery.app指明了webpack的入口文件;包含业务逻辑代码。
//entry.vendor指明了第三方依赖。
//配置上述两个文件的意义在于:vendor中的第三方依赖是很少更新的,可以设置长期缓存在客户端。
//当修改了业务代码,重新生成app.jsx。只需下载新的app.jsx。
//生成以.vendor.js结尾的文件(详见文末的图片:build的结果)


//解释@4: (webpack出口设置)
//在当前根目录下,创建build文件夹,来放将要被构建生成的结果文件bundle.js。

//解释@5:
//css-loader:处理@import,url等css语句;
//style-loader:将css文件放入style标签并插入head;
//既然使用了extract-text-webpack-plugin。说明本不需要style-loader。
//保险起见:style-loader就可以放在fallback中,如果不能成功编译css文件
//并导入到规定的文件中,则使用style-loader


//解释@6: (CommonsChunkPlugin的作用)
//为了生成vendor.js和app.js两个文件,即将项目中第三方依赖代码抽离出来。可使用CommonsChunkPlugin插件
//生成以.vendor.js结尾的文件(详见文末的图片:build的结果)

附录:

build的结果
// 5. webpack和webpack.config.js的关系
在脚本命令:'npm run dev' 即:'webpack-dev-server --hot --host 0.0.0.0'
webpack-dev-server是一个基于Express框架的Node.js服务器(放在devDependencies中的第三方模块),
提供监听文件改动并实时构建的能力。
为了加快打包进程webpack-dev-server是将打包后的文件放到内存中的。
所以我们在项目中是看不到它打包以后生成的文件/文件夹。

webpack-dev-server默认使用根目录下的webpack.config.js配置文件。
当然也可以明确指明:webpack-dev-server --config webpack.config.js。以下为详解:
var path = require('path');
var webpack = require('webpack');
var HtmlwebpackPlugin = require('html-webpack-plugin');

var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, 'build');

module.exports= {
  entry: {
    app: path.resolve(APP_PATH, 'app.jsx')
  },
  output: {
    path: BUILD_PATH,
    filename: 'bundle.js'
  },
  devtool: 'eval-source-map', //解释@1
  devServer: { //解释@2
    historyApiFallback: true,
    hot: true
  },
  resolve: {
    modules: [APP_PATH, "node_modules"],
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        enforce: "pre",
        loaders: ['eslint-loader'], //解释@3
        include: APP_PATH
      },
      {
        test: /\.jsx?$/,
        loaders: ['babel-loader'], //解释@4
        include: APP_PATH
      },
      {
        test: /\.s?css$/,
        loaders: ['style-loader', 'css-loader', 'sass-loader']
      }   
    ]
  },
  plugins: [
    new HtmlwebpackPlugin({
      title: 'Deskmark app'
    }),
    new webpack.HotModuleReplacementPlugin(), //解释@5
  ]
}

//解释@1:(devtool: 'eval-source-map'的作用)
//'devtool'指明是否/如何生成源映射(指明webpack将以什么形式对源码module构建打包)
//开发和生产环境中可使用不同的方式。'eval-source-map'用在开发中可大幅提高持续构建效率。


//解释@2:(devServer的作用)
//在开发模式下,devServer提供开发虚拟服务器以便开发调试,且提供实时刷新加载(其实就是webpack-dev-server的配置项)。
//
//devServer.hot: 启用模块热更新,当源码有变动并保存后,页面自动刷新。
//注意:此处仅仅是表示启用。 启用后,webpack会自动添加 真正发挥模块热更新作用的webpack.HotModuleReplacementPlugin插件
//
//devServer.historyApiFallback: true指明页面出错不弹出404页面

//解释@3:(eslint-loader在webpack中的使用)
//表示在用babel编译.jsx代码之前,先检查代码是否符合规则。
//eslint-loader会在在根目录下查找.eslintrc文件,查看具体规则。

//解释@4:(babel-loader的作用)
//babel-loader在执行编译的过程中,会从项目的根目录下的 .babelrc文件中读取配置。

//解释@5:(webpack.HotModuleReplacementPlugin()的作用)
//HotModuleReplacementPlugin依赖webpack-dev-server,后者在打包文件改变时更新打包文件或刷新整个页面,前者只刷新修改的部分。
//new webpack.HotModuleReplacementPlugin()表示直接启用该插件。
//.babelrc文件
{
  "presets": ["es2015", "react", "stage-2"],
  "plugins": ["transform-object-rest-spread"]
}
//.eslintrc文件
{
  "parser": "babel-eslint",
  "extends": "airbnb",
  "parserOptions": {
    "ecmaFeatures": {
      "experimentalObjectRestSpread": true,
      "jsx": true
    },
    "sourceType": "module"
  },
  "rules": {
    "no-use-before-define": [2, "nofunc"]
  }
}

//"extends": "airbnb"该行代码使用Airbnb的ESLint配置
//(配置包含了jsx和React的规则),可在node_modules包中查看。

//使用时,直接在rules中配置需要检查的规则。no-use-before-define指明变量必须先定义后使用。
//"0"表示忽略问题,等同于"off";
//"1"表示给出警告,等同于"warn";
//"2"表示直接报错,等同于"error"。

//当需要覆盖airbnb的规则时,直接在rules中写明即可:
//
//改进:利用eslint对react项目的源码进行代码规则检查
(Airbnb的扩展规则中,已经包含了jsx和react的规则)

参考.eslintrc详细配置项1
参考.eslintrc详细配置项2

相关文章

网友评论

      本文标题:React项目模板-webpack解析

      本文链接:https://www.haomeiwen.com/subject/gucznqtx.html