基于webpack3.x从0开始搭建React开发环境

在开发react单页面的时候无可避免的要使用到webpack打包,今天就从零开始搭建一个react的开发环境。

需要实现的功能有:

  1. 使用Babel编译ES6
  2. 编译.jsx文件
  3. 实现热更新
  4. 编译CSS预处理文件Less,CSS后处理文件PostCSS
  5. 提取公共的CSS样式到一个公共的文件中
  6. 压缩js,减小js文件的大小
  7. 抽取公共的第三方js库,并且打包的时候第三方js文件的名称不会变,方便客户端缓存
  8. 压缩img等资源文件,过小的资源文件就编程dataURL的形式直接写在CSS中
  9. 可以访问静态的资源文件,图片等
  10. 代理

一、完成基本的目录结构与基本打包

  1. 新建一个reactWebpack文件夹,进入该文件夹并执行 npm init 初始化一个项目(生成package.json文件),新建如下目录结构:

    reactWebpack
    -- dist(打包后文件)
    -- src(业务源码)
        |-- index.html|-- app.js
    -- webpack.config.js(webpack配置文件)
    -- .babelrc(babel配置文件)
    -- package.json
  2. 在reactWebpack文件夹下安装以下依赖:

    npm install -D webpack@3.11.0

    如果全局环境下没有webpack那么建议也全局安装

    npm install -g webpack@3.11.0

  3. 修改webpack的配置文件 webpack.config.js ,如下:

    var path = require('path');module.exports = {entry: './src/index.js',output: {path: path.resolve(__dirname, 'dist'), // 这里需要绝对路径filename: '[name].js'}
    }
  4. 到这一步就可以使用webpack打包项目中依赖的js了,但是使用jsx和目前浏览器还不能完美支持的ES6语法还需要转译,将ES6等新的特性和jsx转换成ES5语法让浏览器不支持的特性得以支持。

    安装依赖 npm install babel-core babel-loader babel-preset-react babel-preset-2015

    修改webpck.config.js加上对js文件处理的loader部分:

    var path = require('path');module.exports = {entry: './src/index.js',output: {path: path.resolve(__dirname, 'dist'),filename: '[name].js'},module: {rules: [{test: /\.js|\.jsx$/, use: ['babel-loader'], exclude: path.resolve(__dirname, 'node_modules')}]}
    }
  5. 修改babel配置文件.babelrc文件

    {"presets": ["es2015", "react"]
    }
  6. 配置打包html模板,先安装依赖:

    npm install -D html-webpack-plugin

    修改webpack.config.js文件如下

    var path = require('path');
    var HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {entry: './src/index.js',output: {path: path.resolve(__dirname, 'dist'),filename: '[name].js'},module: {rules: [{test: /\.js$/, use: 'babel-loader', exclude: path.resolve(__dirname, 'node_modules/')}    ]},plugins: [new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',inject: true})]
    }
  7. 安装项目依赖react等:

    npm install --save react react-dom react-router-dom

    修改index.html和app.js文件

    index.html 如下:

    <!DOCTYPE html>
    <html>
    <head><meta charset="utf-8" /><title></title>
    </head>
    <body>
    <div id="container"></div>
    </body>
    </html>

    app.js 如下:

    import ReactDOM from 'react-dom'
    import React from 'react'ReactDOM.render(<div>我是组建</div>, document.getElementById('container'))

到这里基本的目录结构已经搭建完成,并且可以在根目录下执行webpack进行打包。打包完成后在dist文件夹下会有index.html和app.js文件。

二、配置webpack热加载

  1. 安装如下依赖:

    npm install -D webpack-dev-server@2.7.1

    注意:是2.7.1版本

  2. 在根目录下添加 dev.conf.js 文件:

    var webpack = require('webpack')
    var WebpackDevServer = require('webpack-dev-server')var config = require('./webpack.config.js')
    var port = '8899'
    var host = 'localhost'
    var options = {contentBase: './dist',hot: true,host: host,port: port // 这里最好加上port
    }WebpackDevServer.addDevServerEntrypoints(config, options)
    var compiler = webpack(config)
    var server = new WebpackDevServer(compiler, options)server.listen(port, function(){console.log(host + ':' + port + '启动成功')
    })
  3. 修改webpack.config.js文件,添加了两个插件:

    var path = require('path')
    var webpack = require('webpack')
    var HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = {entry: './src/app.js',output: {path: path.resolve(__dirname, 'dist'),filename: '[name].js'},devtool: 'inline-source-map', // 生成map映射,方便定位错误module: {rules: [{test: /\.js$/, loader: 'babel-loader' }]},plugins: [ new webpack.NamedModulesPlugin(), // 新加new webpack.HotModuleReplacementPlugin(), // 新加new HtmlWebpackPlugin({template: './src/index.html',path: path.resolve(__dirname, 'dist'),chunks: ['main']})]
    }

到这里开发环境配置完成,在根目录下运行 node dev.conf.js 即可启动一个开发服务器。

三、调整目录结构

在上面已经完成可webpak开发环境的配置,下面要配置打包环境。在开始配置打包环境之前需要调整一下目录的结构。因为在开发环境(dev)和打包(build)上线的环境有一部分不同,但是基础部分又是相同的,所以需要合理的计划一下。

主要分为三个配置文件 dev.conf.js(原webpack.config.js一部分内容)、build.conf.js和base.conf.js(原大部分webpack.config.js内容),这三个文件会被放在新建的build文件夹下。

调整后的文件目录如下:

reactWebpack--build|--base.conf.js|--dev.conf.js|--build.conf.js-- dist(打包后文件)-- src(业务源码)|-- index.html|-- app.js-- .babelrc(babel配置文件)-- package.json
  1. 修改base.conf.js文件如下:

    var path = require('path')
    var webpack = require('webpack')
    var HtmlWebpackPlugin = require('html-webpack-plugin')function resolve(dir){return path.resolve(__dirname, '../', dir)
    }module.exports = {entry: './src/app.js',output: {path: resolve('dist'),filename: '[name].js'},devtool: 'inline-source-map',module: {rules: [{test: /\.js$/, loader: 'babel-loader',exclude: resolve('node_modules')}]},plugins: [ new HtmlWebpackPlugin({template: './src/index.html',path: resolve('dist'),chunks: ['main']})]
    }
  2. 安装依赖 npm install -D webpack-merge并修改dev.conf.js文件如下:

    var webpack = require('webpack')
    var WebpackDevServer = require('webpack-dev-server')
    var merge = require('webpack-merge')// 开发环境配置,这部分配置在打包的时候是不需要的
    var webpackDevConfig = {plugins: [new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin()]
    }// 下面是服务器配置
    var config = merge(webpackDevConfig, require('./base.conf.js'))
    var options = {contentBase: '../dist',hot: true,host: 'localhost'
    }
    var port = '8899'WebpackDevServer.addDevServerEntrypoints(config, options)
    var compiler = webpack(config)
    var server = new WebpackDevServer(compiler, options)server.listen(port, function(){console.log('启动成功')
    })

上面的目录结构已经调整完成,在根目录下运行 node build/dev.conf.js 即可开启开发服务器。

四、配置完善的webpack打包部分

webpack是按照依赖打包的,但是如果不处理的话所有的依赖会被打包到一个文件中,也就是说无论是第三方依赖,还是自己写的业务逻辑都会在同一个打包好的文件(main.js)中。

这会有很多问题,例如:

  • 不方便客户端缓存,客户端肯定会缓存main.js,但是如果我们修改了业务代码然后打包上线,这个main.js名称没有改变,而内容却是修改了,并且客户端缓存了main.js所以不一定会去获取新的main.js,这样就导致了新的代码并没有及时的被使用
  • 没有将第三方代码和业务代码分离,分离后第三方代码是可以让客户端缓存以节省加载时间,因为我们修改的是自己的业务代码
  • 上面的配置还没有去除注释、警告和压缩代码以减小代码体积

    1. 压缩代码JS代码

    修改build.conf.js文件如下:

    var path = require('path')
    var webpack = require('webpack')
    var merge = require('webpack-merge')
    var baseConfig = require('./base.conf.js')var buildConfig = {plugins: [new webpack.DefinePlugin({'process.env': {'NODE_ENV': JSON.stringify('production')}}),new webpack.optimize.UglifyJsPlugin() // 新加]
    }module.exports = merge(buildConfig, baseConfig)

在根目录下执行webpack build/build.conf.js,即可看到打包出的文件会小很多。

  1. 提取第三方代码单独打包

    修改代码如下:

    var path = require('path')
    var webpack = require('webpack')
    var merge = require('webpack-merge')
    var baseConfig = require('./base.conf.js')var buildConfig = {plugins: [new webpack.DefinePlugin({'process.env': {'NODE_ENV': JSON.stringify('production')}}),new webpack.optimize.CommonsChunkPlugin({name: 'vender', // 指定公共 bundle 的名称minChunks: function (module, count) {console.log(count)return (module.resource &&/\.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0)}}),new webpack.optimize.CommonsChunkPlugin({name: 'manifest', // 提取webpack的运行时代码chunks: ['vender']}),new webpack.optimize.UglifyJsPlugin()]
    }module.exports = merge(buildConfig, baseConfig)
  2. 为文件名添加hash,当修改的时候文件名发生变化,让客户端及时获取变化的文件,同时缓存没有改变的文件。

    修改base.conf.js文件如下:

    var path = require('path')
    var webpack = require('webpack')
    var HtmlWebpackPlugin = require('html-webpack-plugin')function resolve(dir){return path.resolve(__dirname, '../', dir)
    }module.exports = {entry: './src/app.js',output: {path: resolve('dist'),filename: '[name]-[chunkHash].js' // 新加 chunkHash内容改变的时候chunkHash才会改变},devtool: 'inline-source-map',module: {rules: [{test: /\.js$/, loader: 'babel-loader',exclude: resolve('node_modules')}]},plugins: [ new HtmlWebpackPlugin({template: './src/index.html',path: resolve('dist'),chunks: ['main']})]
    }
  3. 因为加上了chunkHash新生成的文件不会覆盖老文件,那么就会产生很多文件,并不能立马找到目标文件。这时可以考虑先清空打包的目标文件夹dist

    安装 npm install -D clean-webpack-plugin

    修改 build/build.conf.js文件如下

    var path = require('path')
    var webpack = require('webpack')
    var merge = require('webpack-merge')
    var baseConfig = require('./base.conf.js')
    var Clean = require('clean-webpack-plugin')var buildConfig = {plugins: [new webpack.DefinePlugin({'process.env': {'NODE_ENV': JSON.stringify('production')}}),new webpack.optimize.CommonsChunkPlugin({name: 'vender', // 指定公共 bundle 的名称minChunks: function (module, count) {console.log(count)return (module.resource &&/\.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0)}}),new webpack.optimize.CommonsChunkPlugin({name: 'manifest',chunks: ['vender']}),new webpack.optimize.UglifyJsPlugin(),new Clean(['dist']) // 新加]
    }module.exports = merge(buildConfig, baseConfig)

待续。。。。。。。。。。。。。。。。。。。。。。。。。。。

后续:1.CSS预处理器和后处理器的编译 2. 图片的加载 5. 跨域代理的配置 6. 依据react-router做代码分割

参考:

​ webpack中文文档

​ vue-cli生成的webpack配置文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

死机简单配置

编写整个框架的目的是为了处理应用程序的配置。 我更喜欢一种简单的方法。 如果通过配置我们的意思是“ 部署之间可能有所不同的所有内容 ”&#xff0c;那么我们应该尝试使配置保持简单。 在Java中&#xff0c;最简单的选项是不起眼的属性文件。 属性文件的缺点是&#xff0c…

VMWARE虚拟机环境网卡3种模式介绍

NAT模式&#xff1a;相当于你的虚拟机通过你的宿主机上网 桥接模式&#xff1a;相当于你的虚拟机和宿主机同在一个局域网通过静态屁访问网络 仅主机模式&#xff1a;虚拟机只能和宿主机通信&#xff0c;但宿主机不会为虚拟机提供任何路由服务&#xff0c;不能连接到实际网络中转…

一个网站的诞生- MagicDict开发总结2 [ACCESS的烦恼]

说到数据库&#xff0c;有很多很多选择&#xff0c;除了MS-SQL&#xff0c;Oracle&#xff0c;SQLite&#xff0c;MySql&#xff0c;这些大家都非常熟悉的同学&#xff0c;还有DB2&#xff0c;IMSDB&#xff08;灰常灰常古老的数据库&#xff0c;用在OS390等Mainframe中&#x…

TS引用JS模块

为TypeScript引用的JS写声明文件 写TypeScript声明文件的时候会有三个困惑&#xff0c;一个是声明文件是什么&#xff1f;一个是声明文件怎么写&#xff1f;还有一个是TS依据什么规则找到我们的声明文件或者说模块。 第一个问题&#xff1a;按照我的理解声明文件就是告诉TS编…

angular模块

深入浅析AngularJS中的模块 模块是AngularJS应用程序的一个组成部分&#xff0c;模块可以是一个Controller、Service服务、Filter过滤器、directive指令&#xff0c;这些都属于模块。 大多数的应用程序都有一个函数入口main文件&#xff0c;用它来进行初始化&#xff0c;加载…

对象应该是不可变的

在面向对象的编程中&#xff0c;如果对象的状态在创建后无法修改&#xff0c;则该对象是不可变的 。 在Java中&#xff0c;不可变对象的一个​​很好的例子是String 。 创建完成后&#xff0c;我们将无法修改其状态。 我们可以要求它创建新的字符串&#xff0c;但是它自己的状…

开源GIS---.Net系列

NASA World WindNASA World Wind是使用.NET开发的一个Windows窗体系统&#xff0c;以地球外观看得角度提供全球定位功能&#xff0c;类似于Google Earth。它结合了美国国家航空航天局(NASA)从卫星拍摄的图像&#xff0c;这些图像应用于Blue Marble, Landsat 7, SRTM, MODIS 以及…

TypeScript中怎么用接口(interface)描述类(静态部分与实例部分)

TypeScript是JavaScript的超集 在看TypeScript官方文档的接口一节的时候对于类的静态部分与实例部分产生了疑问&#xff0c;通过努力得到自认为相对合理的解释&#xff0c;写下此文以记所得&#xff0c;如有谬误感谢指正。 文中大部分代码示例来自TypeScript官网 TS中的接口…

Java黑科技之源:JVMTI完全解读

Java生态中有一些非常规的技术&#xff0c;它们能达到一些特别的效果。这些技术的实现原理不去深究的话一般并不是广为人知。这种技术通常被称为黑科技。而这些黑科技中的绝大部分底层都是通过JVMTI实现的。 形象地说&#xff0c;JVMTI是Java虚拟机提供的一整套后门。通过这套后…

npm install --save

1. npm install&#xff1a;本地安装 2. npm install -g&#xff1a;全局安装 我们在使用 npm install 安装模块或插件时&#xff0c;有两种命令把它们写入到 package.json 文件中去&#xff0c;在 package.json 里面体现出的区别就是&#xff0c;使用 --save 安装的插件&…

其他一些单元测试技巧

在我以前的文章中&#xff0c;我展示了有关JavaBeans单元测试的一些技巧。 在此博客文章中&#xff0c;我将提供有关单元测试某些相当常见的Java代码的另外两个技巧&#xff0c;即实用程序类和Log4J日志记录语句 。 测试实用程序类 如果您的实用程序类遵循与我倾向于编写的相同…

常见的CSS布局

各种常见的CSS布局 在工作中会经常用到很多的布局方式&#xff0c;这里总结一下所遇到的布局&#xff0c;会持续更新。 悬挂布局 实现这种布局的方式有很多&#xff0c;这边主要挑两个&#xff0c;如下&#xff1a; 方式一&#xff1a;使用浮动和块级格式化上下文特性 这种…

netflix数据处理2(转)

原始数据&#xff1a;$head -10 mv_0006890.txt6890:1735266,1,2004-04-021008399,1,2004-06-222360117,2,2003-11-081294425,2,2004-03-15439931,4,2004-03-271583311,1,2004-03-112431832,3,2005-02-13620771,2,2004-03-201110906,1,2004-03-04结果数据&#xff1a;user_id m…

jQuery 效果

显示和隐藏 1. show(speed) &#xff1a;speed 可以取&#xff1a;slow/fast/毫秒 1 $("#show").click(function(){2 $("p").show(1000);3 }); 2. hide(speed) &#xff1a; 1 $("#hide").click(function(…

OSCP-Kioptrix2014-2 漏洞利用

pChart 2.1.3 文件包含漏洞 搜索漏洞查看漏洞理由代码:hxxp://localhost/examples/index.php?ActionView&Script%2f..%2f..%2fetc/passwd 之前的8080端口禁止访问,看看apache的配置:http://192.168.1.78/pChart2.1.3/examples/index.php?ActionView&Script%2f..%2f..…

使用Drools跟踪输出

Drools 6包含一个跟踪输出&#xff0c;可以帮助您了解系统中正在发生的事情&#xff0c;事物执行的频率以及多少数据。 这也有助于理解Drools 6现在是基于目标的算法&#xff0c;它使用链接机制链接评估规则。 有关此的更多详细信息&#xff1a; http://www.javacodegeeks.co…

CodeSmith注册机,支持5.2.2和5.2.1版

CodeSmith&#xff0c;不用说了&#xff0c;大名鼎鼎的代码生成工具。最早是免费的&#xff0c;后来收费啦这个注册机是针对目前新的CodeSmith 5.2.2的&#xff0c;支持Professinal和其他版本。使用的方法&#xff1a;安装原版的试用版本&#xff0c;从官方网站下载运行试用版&…

JS中与正则相关的方法

前面有一篇文章大体介绍了一下JS中正则表达式&#xff0c;而使用正则表达式还需要配合JS中的相关方法&#xff0c;分别是String对象和RegExp对象的方法。今天就来具体介绍一下这些方法。 使用这则表达式的方法可以分为两类&#xff0c;一个是String的几个方法&#xff0c;还有…

JS基础:求一组数中的最大最小值,以及所在位置

1 var arr [0, 5, -3, 6, 2, -6, 10];2 //定义一个最大值和一个最小值&#xff0c;把他们的索引值赋值给固定的两个变量3 var maxValue arr[0];4 var minValue arr[0];5 var maxIndex 0;6 var minIndex 0;7 for …

linux epoll,poll,select

epoll函数用法&#xff0c;还有点poll和select 1&#xff0c;LT的epoll是select和poll函数的改进版。 特点是&#xff0c;读完缓冲区后&#xff0c;如果缓冲区还有内容的话&#xff0c;epoll_wait函数还会返回&#xff0c;直到把缓冲区全部读完。 2&#xff0c;ET的epoll&#…