从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)

从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)

  • 前言
  • 一 准备工作
    • 1 建立项目目录
    • 2 安装webpack
    • 3 准备项目文件结构
  • 二 配置webpack的工作
    • 1 基础配置
    • 2 配置webpack-dev-server
  • 三 使用React开发页面
  • 四 使用Webpack、Babel和React开发页面
    • 1 安装react
    • 2 生成主入口文件
    • 3 生成我们的html
    • 4 引入Bable解析ES6语法和jsx
    • 5 使用Ant Design作为React的UI库
    • 6 使用webpack加载样式表
    • 7 配置按需加载
  • 五 其他配置
    • 1 使用less语法加载器
    • 2 在react中引用图片资源
    • 3 将样式表单独打包发布成css文件
  • 六 发布产品&配置产品环境
    • 1 打包发布时压缩css文件
    • 2 打包发布时压缩js文件
    • 3 资源文件夹优化
    • 4 关于调试代码(source-map)
  • 七 结语

前言

学习即进步。本人一直使用vue框架,对于react框架一直是得闻不如一见。在一些简单的网站学习了react框架的基本教程之后,参照本人一直使用的webpack+bable+vue+iview开发环境。对应着想搭建一个基于react的开发环境,借此来对比,看看到底是哪个框架比较好用,效率高。进过分析,比对,我选择了与react最为般配的ant-design作为前端ul框架。即模式确定为webpack+bable+react+ant-design;如果需要偷懒,可以直接下载我的github项目,开包即用。

一 准备工作

先挂一下我的package.json,小白可以先忽略。项目结束之后可以提供参考。注意 我使用的是webpack4.x的版本。与3.x的部分内容可能不兼容。

 "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-import": "^1.11.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "css-loader": "^2.1.0",
    "file-loader": "^3.0.1",
    "html-webpack-plugin": "^3.2.0",
    "less": "^2.7.3",
    "less-loader": "^4.0.5",
    "mini-css-extract-plugin": "^0.5.0",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "style-loader": "^0.23.1",
    "url-loader": "^1.1.2",
    "webpack": "^4.29.5",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.1.0",
    "webpack-merge": "^4.1.0",
    "uglifyjs-webpack-plugin": "^2.1.1"
  },
  "dependencies": {
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "antd": "^3.13.5"
  }

1 建立项目目录

  • 新建项目文件夹E:\study\webpack 下面简写为 根目录
  • 命令行进入目录,使用npm init指令进行npm的初始化。按照提示依次键入信息,不知道的直接回车。

2 安装webpack

  • 不建议全局安装webpack
  • 局部安装webpack 根目录>cnpm i webpack --save-dev
  • 没有cnpm的话安装一下淘宝镜像,npm install -g cnpm --registry=https://registry.npm.taobao.org
  • 这时自动安装完毕。package.json中devDependencies自动添加了对webpack的依赖。
"devDependencies": {
  "webpack": "^4.0.0",
}

说明1: webpack版本只要是4之后都可以。我这里只是演示
说明2: devDependencies是开发依赖,只会在打包过程中用到,不会包含到最后的代码中
说明3: 如果想安装指定版本的webpack,使用npm install --save-dev webpack@<版本号>格式

3 准备项目文件结构

我们的项目需要脚本,html,样式,图片以及一些其他资源。

│   package.json
├───node_modules
│       └╌╌ 下面是npm包
├───build
│   ├╌╌╌╌╌ build.js
│   ├╌╌╌╌╌ webpack.base.conf.js
│   ├╌╌╌╌╌ webpack.dev.conf.js
│   └╌╌╌╌╌ webpack.prod.conf.js
├───src
│   ├╌╌╌╌╌ main.js
│   └╌╌╌╌╌template
│         └╌╌╌╌╌template.html // 首页的模板
│   └╌╌╌╌╌images
│         └╌╌╌╌╌logo.jpg  

对,暂时我们就准备这些。

二 配置webpack的工作

webpack的工作就一个。根据一个入口文件,通过import,require等建立目标文件之间的关联关系,调用对应文件后缀的loader实现按需加载。有关完整的配置,可以参考我的下一篇文章。我们今天讲的,都是基本的配置。

1 基础配置

首先我们配置文件,打开webpack.base.conf.js,填写如下内容。

module.exports = {
    entry: './src/main', //main.js中的.js可以省略,前面的./不能省
}

有些朋友也许会问,build目录下有那么多js。为什么是webpack.base.conf.js。

首先,我们知道开发一个项目。有开发阶段和打包发布阶段,所以webpack的工作配置,也分为dev(开发)阶段配置和prod(发布产品)配置。开发模式与产品模式的webpack配置最主要的区别就是开发时需要一个热更新的服务器。以便于我们写的代码能够保存一次就能看到最新效果。而发布之后就是生成静态html文件,由产品服务器托管了。还有很多其他的区别,在之后我们会一一讲到。但是,大部分的基本配置都是一样的,所以我们分了3个文件,webpack.base.conf.js中是webpack通用的配置组成,例如入口文件,这绝对是通用的部分。然后我们再把区分的配置分别写到webpack.dev.conf.jswebpack.prod.conf.js中,再通过webpack-merge去合并配置。

package.json中配置webpack的调用方式,在script标签栏内填入

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

理所当然的,我们现在分成了两个指令:build负责打包生成产品文件,dev负责搭建热更新服务器,实时调试我们的代码。

所以,我们在webpack.dev.conf.js中配webpack-dev-server服务器。

2 配置webpack-dev-server

在这里说明一下,为了保证大家安装的包版本跟我一致,安装依赖包的方式为直接在devDependencies中添加相关的版本,然后再调用cnpm install.

找到package.json添加依赖项

 "webpack-dev-server": "^3.1.0",
 "webpack-cli": "^3.2.3"

注意。webpack-dev-server依赖了"webpack-cli中的相关内容,所以也需要添加依赖。

根目录下执行cnpm install.

完成之后,在webpack.dev.conf.js中填入如下内容

const path = require('path');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf')
module.exports = merge(baseWebpackConfig, {
    devtool: 'cheap-module-eval-source-map',
    output: {
        filename: './dist/[hash]app.js', // dist文件夹不存在时,会自动创建
        hashDigestLength: 8 // 默认长度是20
    },
    devServer: {
        contentBase: path.join(__dirname, "../dist"), //网站的根目录为 根目录/dist,如果配置不对,会报Cannot GET /错误
        port: 9000, //端口改为9000
        open: true// 自动打开浏览器,适合懒人
    },
})

webpack-merge也是webpack的库,需要单独安装
找到package.json添加依赖项

 "webpack-merge": "^4.1.0"

根目录下执行cnpm install.

  • webpack.dev.conf.js中通过引用webpack.base.conf.js,再通过merge对比,有的继承,没有的覆盖,这样就实现了公用基础配置的方法。
  • devtool : cheap-module-eval-source-map, devtool的配置比较复杂。这里你们先这样填,表示我可以在dev模式下F12 定位到原始文件debug我的代码。
  • output其实也是webpack基本配置。配置了项目打包生成的文件的存放处。由于我的dev模式和prod模式不一样,所以写在了dev的配置环境下。
  • devserver的配置参数我已经注释了。

好了。现阶段用于dev模式的webpack已经配置好了,接下来我们就可以开始编写我们的应用了。

三 使用React开发页面

使用React框架编写页面的方法有两种,第一种是直接在html文件中直接引用react.js和react-dom.js,然后在后续的脚本中使用React带来的能力。

一个普通的html文件便可以做到。


  
    
    
  
  
    

Hello world

但是这并不能很好的发挥react的作用。我们要使用ES6、JSX、UI重用等特性,因此我们将使用下面的第二种方法。

四 使用Webpack、Babel和React开发页面

1 安装react

react是我们项目运行时需要用到的包,所以我们需要在package.json中添加依赖项。react最终会被打包进我们的app.js中,供应用程序运行。安装单页面react运行环境目前需要2个包 reactreact-dom。我这里安装的是16.x的react(为了适配之后提到的antd):

//--package.json
"dependencies": {
    "react": "^16.0.0",
    "react-dom": "^16.0.0"
  },

然后在根目录cnpm install;

2 生成主入口文件

react安装好了。接下来我们就可以使用它了。在我们上面建立好的src/main.js中填入按照上面的js修改后的如下内容:

//--main.js
import React from 'react';
import ReactDOM from 'react-dom';
var e = React.createElement('p', null, 'This is React');
ReactDOM.render(e, document.getElementById('main'));

这里我们引用了npm包中安装的react和react-dom。仔细一看,

ReactDOM.render(e, document.getElementById('main'));

噢、看来我们至少需要一个html作为父容器,毕竟没有dom,脚本不可能正常运行。

到这里我们发现,react跟Vue一样,需要一个html页面作为最大的容器,所有的内容最后都会被webpack各种loader编译为浏览器可执行的文件,放到html中。

3 生成我们的html

这时候我们就需要webpack的一个插件html-webpack-plugin,来生成html。首先我们需要安装他。这是在项目编译打包阶段需要使用的库,所以我们把他放在devDependencies中。

//--package.json
"devDependencies": {
    "webpack": "^4.0.0",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.1.0",
    "webpack-merge": "^4.1.0",
    "html-webpack-plugin": "^3.2.0",
  }

根目录执行cnpm install.

接下来我们要使用它。这个配置属于通用的基础配置,所以我们继续打开刚才的基础配置文件webpack.base.conf.js,添加如下语句

//--webpack.base.conf.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); //先引入
module.exports = {
    entry: './src/main', //main.js中的.js可以省略,前面的./不能省
    plugins: [
        new HtmlWebpackPlugin()
    ]
}

现在服务器也好了这样我们应该就可以跑着看了。我们在根目录执行npm run dev,没错,由于我们对于webpack-dev-server的配置open:true,在执行完毕之后我们就可以看到自动打开了浏览器,访问了我们配置的9000端口。

当然我们发现我们的浏览器一片空白

我们打开F12调试工具,先不管报的那个错误。我们去source栏查看,发现webpack确实已经帮我们根据入口main.js打包好了能运行的html。dist中是我们打包生成的app.js,并且已经根据我们配置在webpack.dev.conf.js中的输出,即加上8位哈希值相匹配。但是这些文件都是在内存中生成的,本地并不能找到。生成的html中在body标签的下方引用了生成的js。

从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第1张图片

可以点开那个app.js查看一下。发现内部有我们配置在dependencies中的react已经被打包进去了。
从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第2张图片
但是,我们在main.js中的代码引用了html中的元素。然而这个html是webpack自动生成的。所以我们需要修改html-webpack-plugin的配置,用我们自己的html作为模板。

  • 打开webpack.base.conf.js添加对于HtmlWebpackPlugin的配置。关于配置的详解我已经注释。
const HtmlWebpackPlugin = require('html-webpack-plugin'); //第二步导入
module.exports = {
    entry: './src/main', //main.js中的.js可以省略,前面的./不能省
    plugins: [
        new HtmlWebpackPlugin(
            {
                title: 'SEIE5.0', // html5文件中部分
                filename: 'index.html', // 默认是index.html,服务器中设置的首页是index.html,如果这里改成其它名字,那么devServer.index改为和它一样,最终完整文件路径是output.path+filename,如果filename中有子文件夹形式,如`./ab/cd/front.html`,只取`./front.html`
                template: './src/template/template.html', //如果觉得插件默认生成的hmtl5文件不合要求,可以指定一个模板,模板文件如果不存在,会报错,默认是在项目根目录下找模板文件,才模板为样板,将打包的js文件注入到body结尾处
                inject: "body", // true|body|head|false,四种值,默认为true,true和body相同,是将js注入到body结束标签前,head将打包的js文件放在head结束前,false是不注入,这时得要手工在html中加js
            }
        )
    ]
}
</code></pre> 
  <ul> 
   <li>打开<code>src/template/template.html</code>添加如下内容:</li> 
  </ul> 
  <pre><code><html>
  <body>
    <p>Hello world</p>
    <div id='main'/>
    
  </body>
</html>
</code></pre> 
  <p>ok 现在我们已经配置了让webpack按照我们给定的模板作为根容器了。现在我们重新运行<code>npm run dev</code></p> 
  <p><a href="http://img.e-com-net.com/image/info8/9c21eca5bc1f42ce85880e646b177094.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/9c21eca5bc1f42ce85880e646b177094.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第3张图片" width="650" height="195" style="border:1px solid black;"></a></p> 
  <p>没错,已经完成了。现在react能够正常运行了。</p> 
  <blockquote> 
   <p>注意。inject配置的注入一定要在body。如果填写了head的话,react会报一个错误。找不到dom元素。因为加载react的时候,dom还未初始化完毕。</p> 
  </blockquote> 
  <h2>4 引入Bable解析ES6语法和jsx</h2> 
  <p>到这里,你会发现不需要使用Babel,我们就可以使用React开发页面内容了。但是你会注意到,除了import语句是webpack做了兼容性处理的,我所使用的其他语法都是ES5的语法。<br> 如果在main.js中使用JSX语法,webpack构建的时候就会报错。同样地,如果在main.js中添加ES6的语法,尽管webpack构建时不会报错,但生成的app.js文件末尾部分依旧可以找到这部分ES6语法的代码,这样的代码被用户加载到浏览器中执行,是否能被浏览器支持是无法得到保证的。<br> 为此,我们需要引入Babel,让其把所有浏览器可能不支持的语法转换成ES5的语法。</p> 
  <p>使用Babel的方法也有好多种,官网的帮助文档可以根据环境提供对应的帮助。本文是基于Webpack使用Babel,因此无论是增加的依赖库还是配置流程均只对Webpack的场景有效。我们将使用Webpack关于Babel的一个扩展加载器babel-loader关联这两者。</p> 
  <ul> 
   <li>打开<code>package.json</code> 添加安装依赖</li> 
  </ul> 
  <pre><code>//--package.json
 "devDependencies": {
    ...
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2"
  },
</code></pre> 
  <p>上文提到,Babel用于把新版本的JS代码翻译成大多数浏览器都支持的ES5版本的代码。要做到这些翻译,只需要使用对应的扩展即可。例如:</p> 
  <ul> 
   <li>babel-preset-env根据配置环境计算babel对代码填充何种等级的polyfill,已包括es2015的配置,但没有包括stage-x。官方首推。</li> 
   <li>babel-preset-[stage-0、stage-1、stage-2、stage-3]与ES7相关的配置;</li> 
   <li>除此之外,Babel还可以有其他扩展,比如我们希望使用JSX语法,这时需要引入babel-preset-react处理器。</li> 
  </ul> 
  <p>根据官方的推荐,我们暂时先使用这几个:</p> 
  <pre><code> "devDependencies": {
    ...
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
  },
</code></pre> 
  <p>所以bable的依赖包我们先安装5个。然后执行<code>cnpm install</code></p> 
  <ul> 
   <li>bable的配置属于通用的基本配置,所以我们打开刚才的<code>webpack.base.conf.js</code>,添加rules配置</li> 
  </ul> 
  <pre><code>const HtmlWebpackPlugin = require('html-webpack-plugin'); //第二步导入
module.exports = {
    entry: './src/main', //main.js中的.js可以省略,前面的./不能省
    plugins: [
  	    ...
    ],
    module: {
         rules: [
	      {
	        test: /\.js$/,
	        exclude: /node_modules/,
	        use: {
	          loader: 'babel-loader',
	          options: {
	            presets: ['env', 'stage-0', 'react'],
	            plugins: []
	          }
	        }
	      }
    	]
    }
}
</code></pre> 
  <p>这样我们就使用了bable-loader作为js的解析器。依次使用react、stage-0、env插件进行解析。</p> 
  <ul> 
   <li>修改我们的main.js 这时我们可以使用一些jsx语法试试了:</li> 
  </ul> 
  <pre><code>import React from 'react';
import ReactDOM from 'react-dom';
class Text extends React.Component {
  render() {
    return (
      <p>This is a react Component</p>
    );
  }
}
ReactDOM.render(<Text/>, document.getElementById('main'));
</code></pre> 
  <p>在根目录执行<code>npm run dev</code>查看效果</p> 
  <p><a href="http://img.e-com-net.com/image/info8/4d8fb05a929b40ac8cd5e5ec4969e9dc.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/4d8fb05a929b40ac8cd5e5ec4969e9dc.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第4张图片" width="650" height="191" style="border:1px solid black;"></a><br> 没错。这下子我们完成了jsx语法的打包!Babel很好地工作了。</p> 
  <h2>5 使用Ant Design作为React的UI库</h2> 
  <p>就跟iview一样。我们要的各种漂亮的组件不可能由我们自己去一个个实现,这在项目的开发周期限制下是不允许的。于是乎基于React的各种组件UI库相应而生,而我选择<code>Ant Design</code>是因为其与iview风格、api及管网样式几乎一致。可以减少很多学习的时间。<br> 在<code>package.json</code>中添加ant-design依赖,由于是运行时依赖,所以需要加在<code>dependencies</code>中</p> 
  <pre><code>"dependencies": {
    "antd": "^3.13.5",
    "react": "^16.0.0",
    "react-dom": "^16.0.0"
  }
</code></pre> 
  <p>执行<code>cnpm install</code> 安装依赖。</p> 
  <p>好了,现在我们可以直接使用Ant Design的UI了。修改main.js,引入<code>ant-design</code>的<code>DatePicker</code>:</p> 
  <pre><code>import React from 'react';
import ReactDOM from 'react-dom';
import { DatePicker } from 'antd';
class Text extends React.Component {
  render() {
    return (
      <div>
        <p>This is a react Component</p>
        <DatePicker/>
      </div>
    );
  }
}
ReactDOM.render(<Text/>, document.getElementById('main'));
</code></pre> 
  <p>执行<code>npm run dev</code>,在浏览器中可以看到多了个日期选择器,但是没有相应的样式。</p> 
  <h2>6 使用webpack加载样式表</h2> 
  <p>想要在js中引入css样式表,需要添加webpack的加载器,这样在js中引入的css样式将会被webpack构建成以动态方式插入到html文件中。</p> 
  <p>针对css样式,需要下面两个加载器:</p> 
  <ul> 
   <li>style-loader</li> 
   <li>css-loader</li> 
  </ul> 
  <p>我们在<code>package.json</code>中安装如下依赖包</p> 
  <pre><code>  "devDependencies": {
     ...
    "css-loader": "^2.1.0",
    "style-loader": "^0.23.1"
  },
</code></pre> 
  <p>执行<code>cnpm install</code>安装依赖。</p> 
  <p>css-loader的配置属于通用的基本配置,所以我们打开刚才的<code>webpack.base.conf.js</code>,添加css解析器:</p> 
  <pre><code> module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['env', 'stage-0', 'react'],
                        plugins: []
                    }
                }
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    }
</code></pre> 
  <blockquote> 
   <p>注意:因为antd的样式是放在node_modules中的,不要在css的loader中添加exclude命令刨除掉node_modules目录。</p> 
  </blockquote> 
  <p>然后我们在main.js中引入antd的样式表:</p> 
  <pre><code>//--main.js
...
import { DatePicker } from 'antd';
import 'antd/dist/antd.css';  // Add
...
</code></pre> 
  <p>再次执行热更新服务器查看效果。发现时间选择器已经有样式了。</p> 
  <h2>7 配置按需加载</h2> 
  <p>不知道大家有没有发现现在页面的加载速度明显变慢了。这里是因为上述方法实际上加载整个antd包到最终生成的app.js文件中了。控制台也会看到相应的警告:<br> <img src="http://img.e-com-net.com/image/info8/d3b3bcbc3ad0495fb2498c192887e02b.jpg" alt="在这里插入图片描述" width="650" height="15"><br> 这里很明显,我们需要配置按需加载。配置按需加载需要使用另外一个Babel的插件<code>babel-plugin-import</code>,在<code>package.json</code>中添加引用:</p> 
  <pre><code>"devDependencies": {
	...
    "babel-plugin-import": "^1.11.0"
    ...
  }
</code></pre> 
  <p>执行<code>cnpm install</code>安装依赖。</p> 
  <p>然后修改<code>webpack.base.conf.js</code>中bable加载的方式,使用插件<code>babel-plugin-import</code>:</p> 
  <pre><code>module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['env', 'stage-0', 'react'],
                        plugins: [['import', { "libraryName": "antd", "style": "css" }]]//--通过bable-plugin-import依赖 实现antd按需加载
                    }
                }
            }
        ]
    }
}
</code></pre> 
  <p>大工告成。打包生成的app.js由13w行缩小到了5w行。注意,配置完按需加载之后,<code>main.js</code>中就不需要在手动引入anti的css样式了,所以我们可以去掉这一行。发现时间选择器能够正常加载样式。</p> 
  <blockquote> 
   <p>import ‘antd/dist/antd.css’;</p> 
  </blockquote> 
  <h1>五 其他配置</h1> 
  <h2>1 使用less语法加载器</h2> 
  <p>less是比较主流的样式语法。我在项目中经常使用,同样的,如果你也想在该项目中使用less语法,那么就需要使用less-loader。</p> 
  <ul> 
   <li>在项目src文件夹下新建一个styles文件夹,专门放置我们项目中用到的各种样式,文件夹下新建一个<code>main.less</code></li> 
  </ul> 
  <pre><code>#main
{
    .my-image{
        width: 400px;
        height: 500px;
    }
}
</code></pre> 
  <ul> 
   <li>在<code>main.js</code>中增加一个类名为<code>my-image</code>的div元素,并且import<code>main.less</code></li> 
  </ul> 
  <pre><code>import React from 'react';
import ReactDOM from 'react-dom';
import { DatePicker } from 'antd';
import './styles/main.less'
// import 'antd/dist/antd.css';  // Add
class Text extends React.Component {

    render() {
        return (
            <div>
            <p>This is a react Component123</p>
            <div className = "my-image" ></div>
            <DatePicker/>
            </div>
        );
    }
}
ReactDOM.render(<Text />, document.getElementById('main'));
</code></pre> 
  <blockquote> 
   <p>注意: react语法中class被替换为了className</p> 
  </blockquote> 
  <p>当然,less是无法被webpack识别的。所以对应的,我们需要为less添加对应的加载器。这里我们就需要<code>less-loader</code>了,当然,less-loader依赖less</p> 
  <ul> 
   <li>在<code>package.json</code>中添加依赖:</li> 
  </ul> 
  <pre><code>//--package.json
  "devDependencies": {
	...
   "less": "^2.7.3",
    "less-loader": "^4.0.5",
    ...
  }
</code></pre> 
  <p>执行<code>cnpm install</code>安装依赖。</p> 
  <ul> 
   <li>在<code>webpack.base.conf.js</code>中添加less后缀文件的加载器:</li> 
  </ul> 
  <pre><code>...
    {
         test: /\.css$/,
         use: ['style-loader', 'css-loader']
     },
     {
         test: /\.less$/,
         use: ['style-loader', 'css-loader', 'less-loader']
     }
 ...
</code></pre> 
  <p>这样配置是因为<code>less-loader</code>依赖<code>css-loader</code>,而<code>css-loader</code>依赖于<code>style-loader</code>;<br> 运行服务器,发现样式表被正常应用到了html文件中。打开<code>F12</code>调试工具,发现所有的样式被编译后转化为了样式表被放在了<code>head</code>标签上:<br> <a href="http://img.e-com-net.com/image/info8/d583db3528764ccdbbb556bcbce1a6eb.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/d583db3528764ccdbbb556bcbce1a6eb.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第5张图片" width="650" height="230" style="border:1px solid black;"></a></p> 
  <h2>2 在react中引用图片资源</h2> 
  <p>我们在项目中必不可少的就是引用图片资源。对于图片资源,我们也需要使用对应的loader,来确保webpack对其能够进行正常的处理。为此我们需要引入<code>url-loader</code>对于图片资源进行处理。</p> 
  <ul> 
   <li>安装url-loader</li> 
  </ul> 
  <pre><code>"devDependencies": {
    ...
    "url-loader": "^1.1.2"
  }
</code></pre> 
  <p>然后执行<code>cnmp install</code></p> 
  <ul> 
   <li>在<code>webpack.base.conf.js</code>中添加对应的解析器</li> 
  </ul> 
  <pre><code>...
 {
     test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
     loader: 'url-loader',
     options: {
         limit: 10000,
         name: 'img/[name].[hash:7].[ext]'
     }
 }
 ...
</code></pre> 
  <p>表示对如上后缀资源的都采用url-loader处理。</p> 
  <p><code>limit</code> 属性表示,当资源文件的大小没有超过该值时(单位:字节),编译过后统一转换为base64编码在项目中引用。超过之后,按照<code>name</code>属性配置的目录生成在<code>打包根目录</code>下,以命名规则进行命名。我们这里先设置为10000.</p> 
  <p>这时我们修改原先的main.less,将div设置一个一个背景图片</p> 
  <pre><code>#main
{
    .my-image{
        width: 400px;
        height: 500px;
        background: url("../images/logo.png")
    }
}
</code></pre> 
  <p>打开<code>dev</code>服务器,发现图片能正常显示。打开<code>F12</code>查看图片,发现图片被转为了base64编码:</p> 
  <p><a href="http://img.e-com-net.com/image/info8/f300db5359db4918b0fe525538e7c93e.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/f300db5359db4918b0fe525538e7c93e.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第6张图片" width="650" height="135" style="border:1px solid black;"></a><br> 然后我们再修改limit属性,将其设置为很小的数字 8.再次重启服务器,查看对比结果。</p> 
  <p>嗷。居然报错了~</p> 
  <p><a href="http://img.e-com-net.com/image/info8/d18b88c4fe59447fac68017e2eeea6a7.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/d18b88c4fe59447fac68017e2eeea6a7.jpg" alt="在这里插入图片描述" width="650" height="73"></a></p> 
  <p>原因很简单,因为图片大小超过了设定的大小,url-loader需要调用<code>file-loader</code>进行文件复制和拷贝等操作,所以需要安装<code>file-loader</code></p> 
  <pre><code>//--package.json
 "devDependencies": {
    "file-loader": "^3.0.1"
  }
</code></pre> 
  <p>执行<code>cnpm install</code> 安装后重新执行,重启服务器,得到正确的结果:</p> 
  <p><a href="http://img.e-com-net.com/image/info8/529401bd616940d3a3869cb8d98c8dac.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/529401bd616940d3a3869cb8d98c8dac.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第7张图片" width="650" height="135" style="border:1px solid black;"></a></p> 
  <p>这时,dist下自动生成了img目录,将原有的图片拷贝了过来,并进行了重命名:</p> 
  <p><a href="http://img.e-com-net.com/image/info8/906fdc97e2b64c978b3b931a502840e2.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/906fdc97e2b64c978b3b931a502840e2.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第8张图片" width="650" height="147" style="border:1px solid black;"></a></p> 
  <h2>3 将样式表单独打包发布成css文件</h2> 
  <p>通过上面的例子我们发现,所有的样式都被放到了编译后的html的头部中,如果想将所有的样式统一打包到一个文件中,岂不是很美观。要做到这样,我们需要使用另外一个插件<code>mini-css-extract-plugin</code>.其实在webpack3.x的时候,大家都是采用的<code>extract-text-webpack-plugin</code>进行css的单独处理。但是在4.x,该插件并不支持,并且在4.x官网推荐使用的就是<code>mini-css-extract-plugin</code>,所以我们今天就以该插件为例。</p> 
  <ul> 
   <li>在<code>package.json</code>中安装依赖:</li> 
  </ul> 
  <pre><code> "devDependencies": {
    ...
    "mini-css-extract-plugin":"^0.5.0"
  },
</code></pre> 
  <p>执行<code>cnpm install</code>安装依赖。</p> 
  <ul> 
   <li>打开<code>webpack.base.conf.js</code>,先修改less文件的加载方式,将原先依赖的<code>style-loader</code>替换为<code>MiniCssExtractPlugin.loader</code></li> 
  </ul> 
  <pre><code>//--webpack.base.conf.js

 const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //--注意需要引入
  ...
  module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
            }
           ...
        ],
    }
</code></pre> 
  <ul> 
   <li>在<code>webpack.base.conf.js</code>的<code>plugins</code>配置选项中声明使用该plugin并且添加其配置</li> 
  </ul> 
  <pre><code>//--webpack.base.conf.js
plugins: [
        new HtmlWebpackPlugin({
           ...
        }),
        new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename: "[id].css"
        })
 ]
</code></pre> 
  <ul> 
   <li>执行npm run dev。</li> 
  </ul> 
  <p><a href="http://img.e-com-net.com/image/info8/16c2d67ce6ea44a09e9935aaf22f7e35.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/16c2d67ce6ea44a09e9935aaf22f7e35.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第9张图片" width="650" height="139" style="border:1px solid black;"></a><br> 没错!我们现在将css单独独立到了一个文件中了(暂时不管路径,会在下一节提及),并且查看html,在<code>head</code>部分注入了对main.css的引用,原先在<code>style</code>标签中引用的样式消失了。现在大家应该明白<code>style-loader</code>的作用了吧。由于被替换为了<code>MiniCssExtractPlugin.loader</code>,样式注入的流程被替代了。所以不会在html文件的<code>style</code>标签中注入样式了。</p> 
  <p><a href="http://img.e-com-net.com/image/info8/60274bee6aaf4822b0642a35aed9913a.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/60274bee6aaf4822b0642a35aed9913a.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第10张图片" width="650" height="115" style="border:1px solid black;"></a><br> 依葫芦画瓢,我们把anti-design的样式也修改注入方式,全部放到main.css中。</p> 
  <pre><code>//--webpack.base.conf.js

 const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //--注意需要引入
  ...
  module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
            }
           ...
        ],
    }
</code></pre> 
  <p>重新运行<code>npm run dev</code>。</p> 
  <p>完美。现在html中已经没有一大坨样式了,仅有对<code>main.css</code>的引用打开<code>main.css</code>,发现原来的样式都被放到了这里。<br> <a href="http://img.e-com-net.com/image/info8/25499cdc9a42466d842ce4960d7d85d5.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/25499cdc9a42466d842ce4960d7d85d5.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第11张图片" width="650" height="170" style="border:1px solid black;"></a></p> 
  <h1>六 发布产品&配置产品环境</h1> 
  <p>截止到上面为止,我们讨论的都是使用<code>webpack-dev-server</code>构建服务器,然后在内存中加载对于webpack编译生成的文件,主要用于开发阶段使用的。虽然配置的写法都在<code>webpack.base.conf.js</code>中,但是我们使用的指令<code>npm run dev</code>使用的都是<code>webpack.dev.conf.js</code>中的配置。当我们发布产品的时候,我们就需要一些不同于<code>dev</code>的配置选项了。</p> 
  <ul> 
   <li>打开<code>webpack.prod.conf.js</code> ,按照<code>webpack.dev.conf.js</code>填写如下内容:</li> 
  </ul> 
  <pre><code>const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf')

module.exports = merge(baseWebpackConfig, {

})
</code></pre> 
  <ul> 
   <li>在根目录执行<code>npm run build</code>;</li> 
  </ul> 
  <p>发现我们的项目根目录下多了一个<code>dist</code>文件夹,打开一看,哇塞。居然就是我们刚才所有在<code>dev</code>模式下的生成的文件结构:<br> <a href="http://img.e-com-net.com/image/info8/2d074e9019a843c8b5e46e6e6fa8b914.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/2d074e9019a843c8b5e46e6e6fa8b914.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第12张图片" width="400" height="133" style="border:1px solid black;"></a></p> 
  <p>我们双击<code>index.html</code> 完美,浏览器中也能呈现和<code>dev</code>模式下的一模一样的效果。注意,这里的所有资源都是可以被浏览器直接识别的,没有less,没有es6,也没有jsx等等,只有html,css,js。这就是编译发布的意义,这样所有的浏览器都能兼容运行我们的项目了。只需要一个服务器,将内容放上去托管,大家就可以访问我们的网页了。</p> 
  <p>到这里,其实你已经可以开始开发项目了。但是,还是有一些问题存在的,我们上面<code>prod</code>的配置是完全使用<code>base</code>的配置项。毕竟编译发布的配置和dev的配置还是有区别的。在这里,我列举几点问题和解决,其余的定制配置,还是需要大家自己去实现。只需要记得,在<code>webpack.prod.conf.js</code>中配置编译发布环境,在<code>webpack.dev.conf.js</code>中配置开发环境。在<code>webpack.base.conf.js</code>中配置两者共用的环境即可。</p> 
  <h2>1 打包发布时压缩css文件</h2> 
  <p>webpack5可能会内置CSS 压缩器,webpack4需要自己使用压缩器,可以使用 <code>optimize-css-assets-webpack-plugin</code>插件。 设置 <code>optimization.minimizer</code> 覆盖webpack默认提供的即可。</p> 
  <ul> 
   <li>安装<code>optimize-css-assets-webpack-plugin</code></li> 
  </ul> 
  <pre><code>  "devDependencies": {
	...
    "optimize-css-assets-webpack-plugin": "^5.0.1",
	...
  },
</code></pre> 
  <p>执行<code>cnpm install</code></p> 
  <ul> 
   <li>这时我们需要配置<code>webpack.prod.conf.js</code>:</li> 
  </ul> 
  <pre><code>//--webpack.prod.conf.js
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = merge(baseWebpackConfig, {
    optimization: {
        minimizer: [
            new OptimizeCSSAssetsPlugin({})
        ]
    }
})
</code></pre> 
  <p>这里我们使用我们安装的插件,然后执行<code>npm run build</code>即可。没错,这时我们发现我们的<code>main.css</code>已经是压缩过的状态了~<br> <a href="http://img.e-com-net.com/image/info8/de8201ceee2046c8941c680af3d94410.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/de8201ceee2046c8941c680af3d94410.jpg" alt="在这里插入图片描述" width="650" height="56"></a></p> 
  <h2>2 打包发布时压缩js文件</h2> 
  <p>不知道大家有没有发现。在执行上一步之前,我们调用<code>npm run build</code>的时候,生成的<code>main.js</code>都是默认压缩的。那是因为webpack4.x的新特性、webpack4新的Mode,且默认值是production,所以都是默认调用其内置的<code>UglifyJsPlugin</code>进行压缩的。但是我们上一步复写了其默认配置。没有指定js压缩器,所以没有压缩js代码。这时候我们需要重新指定。</p> 
  <ul> 
   <li>下载安装<code>uglifyjs-webpack-plugin</code></li> 
  </ul> 
  <pre><code> "devDependencies": {
    "uglifyjs-webpack-plugin": "^2.1.1"
  },
</code></pre> 
  <p>执行<code>cnpm install</code>安装依赖</p> 
  <ul> 
   <li>打开<code>webpack.prod.conf.js</code> 修改<code>optimization</code>配置:</li> 
  </ul> 
  <pre><code>const UglifyJsPlugin = require('uglifyjs-webpack-plugin');  //--注意需要引入
...
optimization: {
        minimizer: [
            new OptimizeCSSAssetsPlugin({}),
            new UglifyJsPlugin({})
        ]
} 
...
</code></pre> 
  <p>这时 我们重新执行<code>npm run build</code>。ok js变成压缩过的版本了。这样可以打打减少我们项目打包出来文件的体积,提高网页加载的速度。<br> <a href="http://img.e-com-net.com/image/info8/f12776fb61354ca9bdbd293f8d0cd483.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/f12776fb61354ca9bdbd293f8d0cd483.jpg" alt="在这里插入图片描述" width="650" height="53"></a></p> 
  <h2>3 资源文件夹优化</h2> 
  <p>一般webpack打包出来的主流结构为一个static资源文件夹,然后是一个html文件。这样的结构合理,清晰。static文件夹内包含css,img,font等静态资源文件。这时候我们要修改我们项目的打包路径,使之符合这种审美。<br> <a href="http://img.e-com-net.com/image/info8/2b9e5f2d576f4f03bb37bfc81598d78c.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/2b9e5f2d576f4f03bb37bfc81598d78c.jpg" alt="在这里插入图片描述" width="320" height="70"></a></p> 
  <p>我们先来看看我们现在打包生成的目录结构:<br> <a href="http://img.e-com-net.com/image/info8/c960333e5978432c819ce737651babc0.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/c960333e5978432c819ce737651babc0.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第13张图片" width="321" height="147" style="border:1px solid black;"></a><br> 可以看到确实很丑。很乱,只有img文件夹是按照我们的想法的规则的。所以接下来我们要将其结构优化。</p> 
  <ul> 
   <li>首先我们要讲css的生成路径修改一下。改为由<code>css</code>文件夹包裹:<br> 理所当然的,我们想到了我们的<code>MiniCssExtractPlugin</code>,他是我们打包css最后一层调用的插件。于是我们修改他的配置:</li> 
  </ul> 
  <pre><code>//--webpack.base.conf.js
  ...
  new MiniCssExtractPlugin({
        filename: "css/[name].css",
        chunkFilename: "[id].css"
 })
</code></pre> 
  <p>因为官网说,<code>filename</code>的配置方式和<code>chunkFilename</code>的配置方式和<code>webpack</code>完全一致,所以我们尝试修改生成css的路径。<br> 保存之后,执行编译指令<code>npm run build</code>。<br> <a href="http://img.e-com-net.com/image/info8/c09d95e5364643a185f3f816ea3f9c03.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/c09d95e5364643a185f3f816ea3f9c03.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第14张图片" width="315" height="135" style="border:1px solid black;"></a><br> 没错,成功了,我们将<code>main.css</code>打包进了<code>css</code>文件夹下。</p> 
  <ul> 
   <li>由于生成目录是公用配置,<code>dev</code>和<code>prod</code>模式均要使用。所以修改<code>webpack.base.config.js</code>中配置<code>output</code> 优化js的生成目录,并且换个名叫app.js:</li> 
  </ul> 
  <pre><code>//--webpack.base.config.js
module.exports = merge(baseWebpackConfig, {
    output: {
        filename: 'js/app[hash].js', // dist文件夹不存在时,会自动创建
        hashDigestLength: 8 // 默认长度是20
    }
})
</code></pre> 
  <p>记得删除<code>webpack.dev.config.js</code>中<code>output</code>的配置,这样<code>dev</code>模式才能继承到。<br> 我们先运行<code>npm run build</code>编译。<br> <a href="http://img.e-com-net.com/image/info8/3a52428435c94200ba1c7c1324ce09d8.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/3a52428435c94200ba1c7c1324ce09d8.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第15张图片" width="345" height="176" style="border:1px solid black;"></a><br> 没错!现在js也被我们套了一层了。</p> 
  <ul> 
   <li>将所有的资源包裹进<code>static</code>文件夹</li> 
  </ul> 
  <p>这里我们需要了解一个<code>webpack</code>的2个属性<code>output.publicPath</code>和<code>output.path</code>。<code>output.path</code>该属性表示将所有资源打包进根目录下的对应路径内。而<code>output.publicPath</code>表示html在引用这些资源的时候,默认在前面添加的路径。</p> 
  <p><strong>第一步</strong></p> 
  <p>修改一下<code>output.publicPath</code>,由于这是基本配置,所以我们打开<code>webpack.base.config.js</code>,添加如下语句</p> 
  <pre><code>module.exports = {
     ...
    output: {
        filename: './js/app[hash].js', // dist文件夹不存在时,会自动创建
        hashDigestLength: 8,// 默认长度是20
        publicPath:"./static/"
    }
    ...
 }
</code></pre> 
  <p>执行一次<code>npm run build</code> 然后观察生成的html文件。<br> <a href="http://img.e-com-net.com/image/info8/d83d415f001743ef82e2a308a6935f97.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/d83d415f001743ef82e2a308a6935f97.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第16张图片" width="650" height="130" style="border:1px solid black;"></a><br> 大家应该猜到了?就是这个意思,引用资源的前缀都会添加这个。我们的目的达到了。接下来就是把资源放到<code>static</code>文件夹下。</p> 
  <p><strong>第二步</strong><br> 还是上述文件<code>webpack.base.config.js</code> 我们再添加<code>path</code>的配置</p> 
  <pre><code>var path = require('path');//--path是node包中的类。注意引用
module.exports = {
     ...
    output: {
        filename: './js/app[hash].js', // dist文件夹不存在时,会自动创建
        hashDigestLength: 8,// 默认长度是20
        publicPath:"./static/",
        path:path.resolve(__dirname, '../dist/static')
    }
    ...
 }
</code></pre> 
  <p>表示资源生成的路径为取相对路径的dist再拼上static。我们再编译一次。`npm run build</p> 
  <p><a href="http://img.e-com-net.com/image/info8/36ac95b5fc25462995576bb20660f3ef.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/36ac95b5fc25462995576bb20660f3ef.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第17张图片" width="362" height="144" style="border:1px solid black;"></a>`</p> 
  <p>ok。完美。现在只剩下最后一步,将<code>index.html</code>移到<code>static</code>外,与其同级。</p> 
  <p><strong>第三步</strong></p> 
  <p>还是上述文件<code>webpack.base.config.js</code> 我们修改<code>HtmlWebpackPlugin</code>的配置。将<code>filename</code>属性修改为当前目录上一层:</p> 
  <pre><code>...
plugins: [
        new HtmlWebpackPlugin(
            {
                title: 'SEIE5.0', // html5文件中<title>部分
                filename: '../index.html', 
                template: './src/template/template.html',
                inject: "body"
            }
        )
        ...
    ]
    ...
</code></pre> 
  <p><a href="http://img.e-com-net.com/image/info8/d4b0927f9bd648d08e8a47f31da7ffa2.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/d4b0927f9bd648d08e8a47f31da7ffa2.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第18张图片" width="346" height="146" style="border:1px solid black;"></a><br> 哈哈。大功告成。兴奋之余点击index.html查看效果,得意之余,突然发现引用的图片没了。没了。于是赶紧看控制台,果然。图片路径并不能正确找到。<br> <a href="http://img.e-com-net.com/image/info8/20132a49c73b451a877dd5fd11bdfa5d.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/20132a49c73b451a877dd5fd11bdfa5d.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第19张图片" width="650" height="137" style="border:1px solid black;"></a><br> 那一行小字是引用路径,截图的原因看不太清楚:</p> 
  <p><code>file:///E:/github/webpack_test/dist/static/css/static/img/logo.3a54fdd.png</code></p> 
  <p>明显路径不对。本能的,由于请求是在css文件中发出的,所以我们去看打包生成的css文件。虽然被压缩过了,最后一行还是能找到:<br> <a href="http://img.e-com-net.com/image/info8/14e4f249c9964865949841094711b259.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/14e4f249c9964865949841094711b259.jpg" alt="在这里插入图片描述" width="650" height="51"></a><br> 原来是css-loader的问题。由于是相对路径,所以这个url大家都知道,会再css文件夹下查找图片。这当然是找不到的,应该在上一层。所以肯定是<code>url-loader</code>的问题啦。于是我们打开<code>url-loader</code>的配置项,添加<code>publicPath</code>选项,让所有的图片引用都向上一层寻找,这跟webpack的<code>publicPath</code>表示的是同一个意义:</p> 
  <p>打开<code>webpack.base.config.js</code></p> 
  <pre><code>...
module: {
        rules: [
           ...
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 8,
                    name: 'img/[name].[hash:7].[ext]',
                    publicPath:"../"
                }
            },
        ],
    },
    ...
</code></pre> 
  <p>执行<code>npm run build</code>,再次打开浏览器查看最新的html。这次图片的路径就对了。</p> 
  <p><a href="http://img.e-com-net.com/image/info8/15bf079623d1435a8aac379b860de3af.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/15bf079623d1435a8aac379b860de3af.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第20张图片" width="650" height="129" style="border:1px solid black;"></a></p> 
  <p>最后我们来验证下dev是否正常 <code>npm run dev</code> 服务器开启成功,页面加载成功,内存中生成的文件结构也是我们预先设定的结构:</p> 
  <p><a href="http://img.e-com-net.com/image/info8/36c8b09000ac443da6327b7d450042f1.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/36c8b09000ac443da6327b7d450042f1.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第21张图片" width="650" height="112" style="border:1px solid black;"></a></p> 
  <h2>4 关于调试代码(source-map)</h2> 
  <p>执行<code>npm run dev</code>。假如我们现在需要调试代码怎么办?app.js已经被打包的密密麻麻的,根本没办法打断点。这个时候我们就需要配置<code>devtool</code>了。关于<code>devtool</code>的详细配置和各参数的区别,可以参考这篇文章。</p> 
  <pre><code>//-webpack.base.conf.js
module.exports = merge(baseWebpackConfig, {
   ...
    devtool: '#source-map',
   ...
})
</code></pre> 
  <p><code>#source-map</code>表示对应的js生成对应的map映射文件,方便调试。这里还有一个坑我已经帮你们趟了。当我们使用<code>UglifyJsPlugin</code>时,如果要使用<code>source-map</code>,必须要指定<code>sourceMap</code>为true;这是因为在webpack的官方文档中有下面一句话:</p> 
  <blockquote> 
   <p>When using the uglifyjs-webpack-plugin you must provide the sourceMap: true option to enable SourceMap support.</p> 
  </blockquote> 
  <p>也就是当使用了uglifyjs-webpack-plugin 插件时,sourceMap这个值的默认值是false,不开启map。如果要启用map,需要在插件中配置sourceMap值为true。</p> 
  <pre><code>//--webpack.prod.config.js
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = merge(baseWebpackConfig, {
    devtool: '#source-map',
    optimization: {
        minimizer: [
            new OptimizeCSSAssetsPlugin({}),
            new UglifyJsPlugin({sourceMap: true})
        ]
    } 
})
</code></pre> 
  <p>我们运行<code>npm run build</code>查看效果:</p> 
  <p><a href="http://img.e-com-net.com/image/info8/6206f1315f61410eba172cd30b8302b1.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/6206f1315f61410eba172cd30b8302b1.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第22张图片" width="290" height="176" style="border:1px solid black;"></a></p> 
  <p>在js中生成了对应的map文件。</p> 
  <p>我们再执行<code>npm run dev</code> 打开f12 这时候按下Ctrl + P,发现我们可以打开源码中的<code>main.js</code>,加上一个断点,刷新页面:</p> 
  <p><a href="http://img.e-com-net.com/image/info8/f2b71e5d1c58445693c198737441b813.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info8/f2b71e5d1c58445693c198737441b813.jpg" alt="从零开始使用webpack(4.x)+bable+react+ant-design配置单页面应用开发环境(附模板)_第23张图片" width="650" height="159" style="border:1px solid black;"></a><br> ok。现在可以进行调试了。</p> 
  <p>其实<code>dev</code>模式和<code>prod</code>模式应该采用不同的source-map以提高效率。这里我没有深入研究,希望懂的博友们可以留言给予帮助。</p> 
  <h1>七 结语</h1> 
  <p>终于写完了。这篇文章写的很长时间,也是项目一边搭建,一边写的。期间遇到了不少问题,查过很多解决方案。不过一句古话。磨刀不误砍柴工,作为一个通用的模板项目,多付出些心血也是值得的。况且在写这篇博客的同时,也温习并且回顾了webpack很多的知识点。虽然这篇博客涉及的只是一小部分基础的功能,但是应对一般的项目已经绰绰有余了。</p> 
  <p>还有,如果大家在搭建项目的过程中发现什么问题或者疑问,欢迎留言评论,同时也欢迎大牛们的批评指正~</p> 
  <p>github项目地址 https://github.com/worlddai/webpack_react.git</p> 
 </div> 
</div>
                            </div>
                        </div>
                    </div>
                    <!--PC和WAP自适应版-->
                    <div id="SOHUCS" sid="1291655194135830528"></div>
                    <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                    <!-- 文章页-底部 动态广告位 -->
                    <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                </div>
                <div class="col-md-3">
                    <div class="row" id="ad">
                        <!-- 文章页-右侧1 动态广告位 -->
                        <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                        </div>
                        <!-- 文章页-右侧2 动态广告位 -->
                        <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                        </div>
                        <!-- 文章页-右侧3 动态广告位 -->
                        <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(react,webpack)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1940474003030339584.htm"
                           title="Spring Framework 5.0新增的WebClient" target="_blank">Spring Framework 5.0新增的WebClient</a>
                        <span class="text-muted">svygh123</span>
<a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/Java%E5%AD%A6%E4%B9%A0/1.htm">Java学习</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/log4j/1.htm">log4j</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/WebClient/1.htm">WebClient</a>
                        <div>SpringFramework5.0引入了WebClient,这是一个新的非阻塞、响应式Web客户端API,旨在为构建响应式微服务提供更好的支持。WebClient是基于ProjectReactor的响应式流API构建的,它可以高效地处理大量的并发请求,非常适合现代微服务架构。WebClient的主要特性响应式:WebClient基于非阻塞I/O,可以处理大量的并发请求而不会阻塞线程。类型安全:A</div>
                    </li>
                    <li><a href="/article/1940468821890494464.htm"
                           title="spring中maven缺少包如何重新加载,报错java: 程序包org.springframework.web.reactive.function不存在" target="_blank">spring中maven缺少包如何重新加载,报错java: 程序包org.springframework.web.reactive.function不存在</a>
                        <span class="text-muted">东方-教育技术博主</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a>
                        <div>错误原因分析java:程序包org.springframework.web.reactive.function不存在这个错误是由于项目中缺少SpringWebFlux相关依赖导致的。org.springframework.web.reactive.function包属于SpringWebFlux模块(用于响应式Web开发),如果你的项目需要使用该包下的类(如RouterFunction、Serve</div>
                    </li>
                    <li><a href="/article/1940449412002148352.htm"
                           title="使用vue-template-loader将模板编译成渲染函数的Webpack配置技巧" target="_blank">使用vue-template-loader将模板编译成渲染函数的Webpack配置技巧</a>
                        <span class="text-muted">前端布洛芬</span>
<a class="tag" taget="_blank" href="/search/%E5%A4%A7%E7%99%BD%E8%AF%9D%E5%89%8D%E7%AB%AF%E5%85%AB%E8%82%A1/1.htm">大白话前端八股</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>大白话使用vue-template-loader将模板编译成渲染函数的Webpack配置技巧引言:被模板编译逼疯的周三下午你是否也经历过这样的场景:deadline前的周三下午,咖啡因已经失效,屏幕上却跳出Templatecompilationfailed的红色报错。Vue单文件组件(SFC)的.vue格式用腻了,想试试把模板抽成单独的.html文件,结果webpack配置直接给你脸色看。作为每天</div>
                    </li>
                    <li><a href="/article/1940428857941225472.htm"
                           title="GlobalFilter、Filter关系" target="_blank">GlobalFilter、Filter关系</a>
                        <span class="text-muted">m0_63486540</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                        <div>维度GlobalFilterFilter技术体系SpringCloudGateway+WebFluxJavaServletAPI编程模型响应式(Reactive)阻塞式(Imperative)作用范围全局(所有路由)可配置路径模式执行效率更高(基于事件循环)较低(线程池模型)配置方式SpringBean自动注册web.xml或@WebFilter如何选择?如果你正在开发API网关或微服务入口,使用</div>
                    </li>
                    <li><a href="/article/1940406663399927808.htm"
                           title="vue中的toRef" target="_blank">vue中的toRef</a>
                        <span class="text-muted">咔咔咔索菲斯</span>
<a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>在Vue中,toRef函数用于将响应式对象的属性转换为一个独立的ref对象,同时保持与原始属性的关联。其参数格式及用法如下:toRef的参数说明1.参数1:源对象(必须)-类型:Object(通常是通过reactive创建的响应式对象)。-作用:指定需要提取属性的原始对象。-示例:conststate=reactive({count:0});toRef(state,'count');//从stat</div>
                    </li>
                    <li><a href="/article/1940386360187744256.htm"
                           title="image-webpack-loader 使用教程" target="_blank">image-webpack-loader 使用教程</a>
                        <span class="text-muted">毛炎宝Gardener</span>

                        <div>image-webpack-loader使用教程image-webpack-loaderImageloadermoduleforwebpack项目地址:https://gitcode.com/gh_mirrors/im/image-webpack-loader1.项目目录结构及介绍image-webpack-loader是一个用于Webpack的图片压缩加载器。由于该仓库主要是npm包而非独立的应</div>
                    </li>
                    <li><a href="/article/1940382072438845440.htm"
                           title="Webpack中的Loader详解" target="_blank">Webpack中的Loader详解</a>
                        <span class="text-muted"></span>

                        <div>Loader是Webpack中用于处理模块的转换器。它们可以将文件从一种格式转换为另一种格式,比如将TypeScript转换为JavaScript,将SCSS转换为CSS等。使用Loader,可以使Webpack处理各种类型的文件,而不仅仅是JavaScript。1.Loader基础1.1.基础使用Loader就像是一个翻译员,能把源文件经过转化后输出新的结果,并且一个文件还可以链式地经过多个翻译</div>
                    </li>
                    <li><a href="/article/1940377662463733760.htm"
                           title="flutter开发之状态管理、路由管理、" target="_blank">flutter开发之状态管理、路由管理、</a>
                        <span class="text-muted">马拉萨的春天</span>
<a class="tag" taget="_blank" href="/search/flutter%E5%BC%80%E5%8F%91/1.htm">flutter开发</a><a class="tag" taget="_blank" href="/search/%E4%B8%80%E5%A4%A9%E4%B8%80%E8%AF%BB/1.htm">一天一读</a><a class="tag" taget="_blank" href="/search/flutter/1.htm">flutter</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>2.3状态管理#2.3.1简介响应式的编程框架中都会有一个永恒的主题——“状态(State)管理”,无论是在React/Vue(两者都是支持响应式编程的Web开发框架)还是Flutter中,他们讨论的问题和解决的思想都是一致的。所以,如果你对React/Vue的状态管理有了解,可以跳过本节。言归正传,我们想一个问题,StatefulWidget的状态应该被谁管理?Widget本身?父Widget?</div>
                    </li>
                    <li><a href="/article/1940370094110601216.htm"
                           title="Vue 响应式数据传递:ref、reactive 与 Provide/Inject 完全指南" target="_blank">Vue 响应式数据传递:ref、reactive 与 Provide/Inject 完全指南</a>
                        <span class="text-muted"></span>

                        <div>Vue响应式数据传递:ref、reactive与Provide/Inject完全指南理解如何在不同组件层级间传递响应式数据是Vue开发的关键技能。我将深入探讨ref和reactive配合provide/inject的使用场景和最佳实践。响应式数据与跨层级传递架构提供数据无法传递数据provideinject根组件App.vue中间组件Container.vueDeepChild.vue在多层组件嵌</div>
                    </li>
                    <li><a href="/article/1940363414220107776.htm"
                           title="Spring Boot——整合Redis" target="_blank">Spring Boot——整合Redis</a>
                        <span class="text-muted">秋书一叶</span>
<a class="tag" taget="_blank" href="/search/SpringBoot/1.htm">SpringBoot</a><a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                        <div>SpringBoot整合Redis1.什么是Redis?2.Redis的特点3.什么是Springboot?4.SpringBoot整合Redis4.1下载和安装Redis-redis服务配置4.2Springboot导入依赖4.3配置Redis连接信息4.4创建Redis配置类4.5使用RedisTemplate或ReactiveRedisTemplate4.6通过注解整合5.示例5.1查询5.</div>
                    </li>
                    <li><a href="/article/1940356610761224192.htm"
                           title="前端领域 Vite 与 Webpack 的深度对比" target="_blank">前端领域 Vite 与 Webpack 的深度对比</a>
                        <span class="text-muted">前端视界</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a>
                        <div>前端领域Vite与Webpack的深度对比关键词:Vite、Webpack、前端构建工具、模块打包、开发体验、性能优化、ESModules摘要:本文深入对比前端领域两大构建工具Vite和Webpack的核心原理、架构设计和使用场景。通过分析它们的底层机制、开发体验、构建流程和性能表现,帮助开发者理解如何在不同项目需求下做出合理选择。文章包含详细的技术原理图解、实际项目对比示例和未来发展趋势分析。背</div>
                    </li>
                    <li><a href="/article/1940354714021457920.htm"
                           title="muduo" target="_blank">muduo</a>
                        <span class="text-muted">2301_80355452</span>
<a class="tag" taget="_blank" href="/search/php/1.htm">php</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>好的,我们来深入剖析陈硕老师开发的著名C++网络库——muduo。它以“简单、高效、易用”著称,是学习LinuxC++高性能网络编程的绝佳范本。我会尽量详细、通俗地讲解其核心思想、关键组件、源码结构和工作原理。核心思想:Reactor模式(Non-blocking+I/OMultiplexing)muduo的灵魂是Reactor模式。理解它就理解了muduo的一半。想象一下:传统阻塞模型的问题:想</div>
                    </li>
                    <li><a href="/article/1940289279825604608.htm"
                           title="推荐使用:webpack的高效EJS模板加载器 —— ejs-compiled-loader" target="_blank">推荐使用:webpack的高效EJS模板加载器 —— ejs-compiled-loader</a>
                        <span class="text-muted">雷柏烁</span>

                        <div>推荐使用:webpack的高效EJS模板加载器——ejs-compiled-loaderejs-compiled-loaderEJSloaderforwebpack(withoutfrontenddependencies)项目地址:https://gitcode.com/gh_mirrors/ej/ejs-compiled-loader在前端开发的浩瀚星空中,高效的模板引擎和构建工具是构建高性能应</div>
                    </li>
                    <li><a href="/article/1940272508980752384.htm"
                           title="第 1 周:React 源码结构 + 构建系统" target="_blank">第 1 周:React 源码结构 + 构建系统</a>
                        <span class="text-muted"></span>

                        <div>目标:理解monorepo结构看懂React.createElement和JSX转换明白React是如何通过Rollup构建的推荐文件:/packages/react/src/ReactElement.js/scripts/rollup/*构建脚本/packages/shared/*公共方法如何看懂React.createElement和JSX转换一、核心概念:JSX是React.createEl</div>
                    </li>
                    <li><a href="/article/1940270870127767552.htm"
                           title="前端 React.js 项目的性能优化的成功案例分析" target="_blank">前端 React.js 项目的性能优化的成功案例分析</a>
                        <span class="text-muted">前端视界</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E8%89%BA%E5%8C%A0%E9%A6%86/1.htm">前端艺匠馆</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">性能优化</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a>
                        <div>前端React.js项目的性能优化的成功案例分析关键词:React.js性能优化、代码拆分与懒加载、虚拟列表与长列表优化、Webpack深度调优、Fiber架构实践、SSR与SSG落地、React.memo与useCallback最佳实践摘要:本文通过三个真实企业级React项目的性能优化案例,系统解析从性能瓶颈诊断到优化策略落地的完整流程。结合React核心原理(如Fiber架构、虚拟DOMdi</div>
                    </li>
                    <li><a href="/article/1940269355455541248.htm"
                           title="第 3 周:Fiber 架构原理(调和流程)" target="_blank">第 3 周:Fiber 架构原理(调和流程)</a>
                        <span class="text-muted">longhuxiu</span>
<a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a>
                        <div>目标:理解beginWork、completeWork的作用搞懂调和的核心流程推荐文件:ReactFiberBeginWork.jsReactFiberCompleteWork.jsReactChildFiber.js理解beginWork、completeWork的作用在React源码中,beginWork和completeWork是调和(reconciliation)阶段的核心函数,它们构成了</div>
                    </li>
                    <li><a href="/article/1940267214317875200.htm"
                           title="Next.js 安装使用教程" target="_blank">Next.js 安装使用教程</a>
                        <span class="text-muted">小奇JAVA面试</span>
<a class="tag" taget="_blank" href="/search/%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/1.htm">安装使用教程</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a>
                        <div>一、Next.js简介Next.js是一个基于React的服务端渲染(SSR)框架,由Vercel开发和维护。它支持静态生成(SSG)、服务器端渲染(SSR)、API路由等特性,广泛应用于现代Web开发和Jamstack架构中。二、安装前准备2.1安装Node.js访问https://nodejs.org/下载并安装LTS版本。2.2推荐使用包管理器:npm或yarn可通过以下命令验证安装:nod</div>
                    </li>
                    <li><a href="/article/1940229124459130880.htm"
                           title="Vue3 中watch和computed" target="_blank">Vue3 中watch和computed</a>
                        <span class="text-muted">行云&流水</span>
<a class="tag" taget="_blank" href="/search/Vue3/1.htm">Vue3</a><a class="tag" taget="_blank" href="/search/typescript/1.htm">typescript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>Vue3中computed与watch深度解析在Vue3组合中,响应式工具的类型安全使用至关重要。以下是详细说明一、watch侦听器1.基础类型监听实际参数1={{count}}点击import{reactive,ref,watch}from"vue";constcount=ref(0)conststate=reactive({items:[]asstring[]});watch(count,(n</div>
                    </li>
                    <li><a href="/article/1940227864439877632.htm"
                           title="Vue中使用jsx" target="_blank">Vue中使用jsx</a>
                        <span class="text-muted">前端小咸鱼一条</span>
<a class="tag" taget="_blank" href="/search/Vue3/1.htm">Vue3</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>1.jsx的babel配置1.1在项目中使用jsx,需要添加对jsx的支持:jsx通常会通过Babel来进行转换(React编写的jsx就是通过babel转换的)Vue中,只需要在Babel中配置对应的插件即可以下列举需要支持转换的案例:template->vue-loaderrender->不需要转换jsx->babel(es6->es5、ts->js、jsx->js)->render2.vue</div>
                    </li>
                    <li><a href="/article/1940219793562988544.htm"
                           title="reactor-test" target="_blank">reactor-test</a>
                        <span class="text-muted">lang20150928</span>
<a class="tag" taget="_blank" href="/search/reactor/1.htm">reactor</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                        <div>在Reactor中,reactor-test是一个专门用于测试的工具库,它提供了多种功能来帮助开发者验证响应式流的正确性和可靠性。根据我搜索到的资料,reactor-test的三个主要用途可以总结如下:1.使用StepVerifier按步骤验证序列StepVerifier是reactor-test的核心接口之一,它允许你定义和验证响应式序列的每一步行为。你可以通过expectNext、expect</div>
                    </li>
                    <li><a href="/article/1940219667347992576.htm"
                           title="混合推送/拉取(push/pull)模型" target="_blank">混合推送/拉取(push/pull)模型</a>
                        <span class="text-muted">lang20150928</span>
<a class="tag" taget="_blank" href="/search/reactor/1.htm">reactor</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                        <div>Reactor中的create操作符遵循混合推送/拉取(push/pull)模型,这意味着它结合了推送(push)和拉取(pull)两种机制,以实现更灵活和可控的数据流处理。我们可以从以下几个方面来理解这一概念:1.什么是Push(推送)?Push是一种异步的机制,上游操作符(如create)会主动将数据推送到下游。例如,当onMessage被调用时,sink.next(s)会立即将数据发送到订阅</div>
                    </li>
                    <li><a href="/article/1940213997198438400.htm"
                           title="低代码平台架构设计" target="_blank">低代码平台架构设计</a>
                        <span class="text-muted">LINGYI_WEN</span>
<a class="tag" taget="_blank" href="/search/%E4%BD%8E%E4%BB%A3%E7%A0%81/1.htm">低代码</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>1.整体架构概述1.1技术栈选择前端:React+Redux/Vue+Vuex后端:Node.js+Express/SpringBoot数据库:MySQL/PostgreSQL/MongoDB云服务:AWS/Azure/GoogleCloud容器化:Docker+Kubernetes1.2模块划分前端模块:可视化编辑器:用于拖拽和配置组件预览器:实时预览页面效果发布器:将设计好的页面发布到生产环境</div>
                    </li>
                    <li><a href="/article/1940213364156329984.htm"
                           title="全响应式物联网平台(JetLinks)" target="_blank">全响应式物联网平台(JetLinks)</a>
                        <span class="text-muted">deepdata_cn</span>
<a class="tag" taget="_blank" href="/search/IOT/1.htm">IOT</a><a class="tag" taget="_blank" href="/search/%E7%89%A9%E8%81%94%E7%BD%91/1.htm">物联网</a>
                        <div>JetLinks是一个基于Java8、SpringBoot2.x、WebFlux、Netty等开发的物联网基础平台,可用于快速建立物联网相关业务系统。JetLinks定位为PaaS服务的物联网平台,旨在降低物联网企业研发、运营和运维成本,提高物联网项目的落地能力。支持私有化或容器化以单机、集群或微服务的方式部署在任意平台服务器上,可横向拓展。能支持千万级设备连接、百万级数据并发,通过自研React</div>
                    </li>
                    <li><a href="/article/1940207306805407744.htm"
                           title="React Native的滑动手势功能" target="_blank">React Native的滑动手势功能</a>
                        <span class="text-muted">chenbin___</span>
<a class="tag" taget="_blank" href="/search/react/1.htm">react</a><a class="tag" taget="_blank" href="/search/native/1.htm">native</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>ReactNative的滑动手势。首先,我需要回想ReactNative中处理滑动手势的常用方法。ReactNative本身没有内置的滑动手势组件,所以可能需要用PanResponder或者第三方库。PanResponder是ReactNative自带的,可以用来检测触摸事件。记得要在组件的生命周期里正确设置PanResponder,比如在constructor或者useEffect里。然后处理o</div>
                    </li>
                    <li><a href="/article/1940207307648462848.htm"
                           title="react native ‘style‘ 不是‘StyleProp<ImageStyle>‘类型" target="_blank">react native ‘style‘ 不是‘StyleProp<ImageStyle>‘类型</a>
                        <span class="text-muted">chenbin___</span>
<a class="tag" taget="_blank" href="/search/react/1.htm">react</a><a class="tag" taget="_blank" href="/search/native/1.htm">native</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>Type'ViewStyle|TextStyle|ImageStyle'isnotassignabletotype'StyleProp'.Theexpectedtypecomesfromproperty'style'whichisdeclaredhereontype'IntrinsicAttributes&IntrinsicClassAttributes&Readonly'这个TypeScript</div>
                    </li>
                    <li><a href="/article/1940162182775894016.htm"
                           title="SSVEP Next:现代化的 SSVEP 可视化 Web 快速实现" target="_blank">SSVEP Next:现代化的 SSVEP 可视化 Web 快速实现</a>
                        <span class="text-muted">框架主义者</span>
<a class="tag" taget="_blank" href="/search/web/1.htm">web</a><a class="tag" taget="_blank" href="/search/%E8%84%91%E6%9C%BA%E6%8E%A5%E5%8F%A3/1.htm">脑机接口</a>
                        <div>SSVEPNext:现代化的SSVEP可视化Web快速实现在线使用|GithubSSVEP-Next是一个基于React、TypeScript和Vite构建的单页面应用(SPA),用于快速设计和运行稳态视觉诱发电位(SSVEP)实验的视觉刺激界面。该项目继承自quick-ssvep的核心科学算法,并在架构和交互体验上进行了全面升级。主要特性包括:拖拽式可视化设计:用户可通过拖拽和属性面板,直观地在</div>
                    </li>
                    <li><a href="/article/1940154240160821248.htm"
                           title="一文讲清楚React中state和props的区别与联系" target="_blank">一文讲清楚React中state和props的区别与联系</a>
                        <span class="text-muted">许先森森</span>
<a class="tag" taget="_blank" href="/search/React/1.htm">React</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>文章目录一文讲清楚React中state和props的区别1.共同点2.异同点2.1state2.2props3.总结一文讲清楚React中state和props的区别1.共同点往上有各种关于state和props的解释,各式各样,我这里为了大家更好的理解,总结一句话,页面要变化,数据就得变化,数据变化的来源分为state和props也就是说,state和props的改变都能造成React组件的重</div>
                    </li>
                    <li><a href="/article/1940154113102770176.htm"
                           title="React setState执行流程" target="_blank">React setState执行流程</a>
                        <span class="text-muted">lucky_full</span>
<a class="tag" taget="_blank" href="/search/React/1.htm">React</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>第二章ReactsetState执行流程文章目录第二章ReactsetState执行流程一、setState执行流程setState执行流程介绍一、setState执行流程文章介绍为函数式组件,类组件有所不同。setState执行流程介绍代码如下(示例):importReact,{useState}from'react'constTest=()=>{const[count,setCount]=us</div>
                    </li>
                    <li><a href="/article/1940154113811607552.htm"
                           title="详解React setState调用原理和批量更新的过程" target="_blank">详解React setState调用原理和批量更新的过程</a>
                        <span class="text-muted">真的很上进</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E9%9D%A2%E7%BB%8F%E5%85%AB%E8%82%A1%E5%90%88%E9%9B%86/1.htm">前端面经八股合集</a><a class="tag" taget="_blank" href="/search/Web%E5%89%8D%E7%AB%AF%E8%BF%9B%E9%98%B6%E5%90%88%E9%9B%86/1.htm">Web前端进阶合集</a><a class="tag" taget="_blank" href="/search/React%E7%B3%BB%E5%88%97%E4%B8%93%E6%A0%8F/1.htm">React系列专栏</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a>
                        <div>1.ReactsetState调用的原理setState目录1.ReactsetState调用的原理2.ReactsetState调用之后发生了什么?是同步还是异步?3.React中的setState批量更新的过程是什么?具体的执行过程如下(源码级解析):首先调用了setState入口函数,入口函数在这里就是充当一个分发器的角色,根据入参的不同,将其分发到不同的功能函数中去;ReactCompon</div>
                    </li>
                    <li><a href="/article/1940152727929679872.htm"
                           title="antd tabs" target="_blank">antd tabs</a>
                        <span class="text-muted">巴巴_羊</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>#属性classnamehttps://roo.sankuai.com/v2/standard/#/BPC/react</div>
                    </li>
                                <li><a href="/article/112.htm"
                                       title="HQL之投影查询" target="_blank">HQL之投影查询</a>
                                    <span class="text-muted">归来朝歌</span>
<a class="tag" taget="_blank" href="/search/HQL/1.htm">HQL</a><a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a><a class="tag" taget="_blank" href="/search/%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5/1.htm">查询语句</a><a class="tag" taget="_blank" href="/search/%E6%8A%95%E5%BD%B1%E6%9F%A5%E8%AF%A2/1.htm">投影查询</a>
                                    <div>        在HQL查询中,常常面临这样一个场景,对于多表查询,是要将一个表的对象查出来还是要只需要每个表中的几个字段,最后放在一起显示? 
针对上面的场景,如果需要将一个对象查出来: 
HQL语句写“from 对象”即可 
Session session = HibernateUtil.openSession();
		</div>
                                </li>
                                <li><a href="/article/239.htm"
                                       title="Spring整合redis" target="_blank">Spring整合redis</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a>
                                    <div>pom.xml 
 

<dependencies>
		<!-- Spring Data - Redis Library -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redi</div>
                                </li>
                                <li><a href="/article/366.htm"
                                       title="org.hibernate.NonUniqueResultException: query did not return a unique result: 2" target="_blank">org.hibernate.NonUniqueResultException: query did not return a unique result: 2</a>
                                    <span class="text-muted">0624chenhong</span>
<a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a>
                                    <div>参考:http://blog.csdn.net/qingfeilee/article/details/7052736 
org.hibernate.NonUniqueResultException: query did not return a unique result: 2 
        在项目中出现了org.hiber</div>
                                </li>
                                <li><a href="/article/493.htm"
                                       title="android动画效果" target="_blank">android动画效果</a>
                                    <span class="text-muted">不懂事的小屁孩</span>
<a class="tag" taget="_blank" href="/search/android%E5%8A%A8%E7%94%BB/1.htm">android动画</a>
                                    <div>前几天弄alertdialog和popupwindow的时候,用到了android的动画效果,今天专门研究了一下关于android的动画效果,列出来,方便以后使用。 
 
Android 平台提供了两类动画。 一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转、平移、放缩和渐变)。 
第二类就是 Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似。 
 
</div>
                                </li>
                                <li><a href="/article/620.htm"
                                       title="js delete 删除机理以及它的内存泄露问题的解决方案" target="_blank">js delete 删除机理以及它的内存泄露问题的解决方案</a>
                                    <span class="text-muted">换个号韩国红果果</span>
<a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a>
                                    <div>delete删除属性时只是解除了属性与对象的绑定,故当属性值为一个对象时,删除时会造成内存泄露  (其实还未删除) 
举例: 

var person={name:{firstname:'bob'}}
var p=person.name
delete person.name
p.firstname  -->'bob'
// 依然可以访问p.firstname,存在内存泄露</div>
                                </li>
                                <li><a href="/article/747.htm"
                                       title="Oracle将零干预分析加入网络即服务计划" target="_blank">Oracle将零干预分析加入网络即服务计划</a>
                                    <span class="text-muted">蓝儿唯美</span>
<a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a>
                                    <div>由Oracle通信技术部门主导的演示项目并没有在本月较早前法国南斯举行的行业集团TM论坛大会中获得嘉奖。但是,Oracle通信官员解雇致力于打造一个支持零干预分配和编制功能的网络即服务(NaaS)平台,帮助企业以更灵活和更适合云的方式实现通信服务提供商(CSP)的连接产品。这个Oracle主导的项目属于TM Forum Live!活动上展示的Catalyst计划的19个项目之一。Catalyst计</div>
                                </li>
                                <li><a href="/article/874.htm"
                                       title="spring学习——springmvc(二)" target="_blank">spring学习——springmvc(二)</a>
                                    <span class="text-muted">a-john</span>
<a class="tag" taget="_blank" href="/search/springMVC/1.htm">springMVC</a>
                                    <div>Spring MVC提供了非常方便的文件上传功能。 
1,配置Spring支持文件上传: 
DispatcherServlet本身并不知道如何处理multipart的表单数据,需要一个multipart解析器把POST请求的multipart数据中抽取出来,这样DispatcherServlet就能将其传递给我们的控制器了。为了在Spring中注册multipart解析器,需要声明一个实现了Mul</div>
                                </li>
                                <li><a href="/article/1001.htm"
                                       title="POJ-2828-Buy Tickets" target="_blank">POJ-2828-Buy Tickets</a>
                                    <span class="text-muted">aijuans</span>
<a class="tag" taget="_blank" href="/search/ACM_POJ/1.htm">ACM_POJ</a>
                                    <div>POJ-2828-Buy Tickets 
http://poj.org/problem?id=2828 
线段树,逆序插入 
 
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;#define N 200010struct</div>
                                </li>
                                <li><a href="/article/1128.htm"
                                       title="Java Ant build.xml详解" target="_blank">Java Ant build.xml详解</a>
                                    <span class="text-muted">asia007</span>
<a class="tag" taget="_blank" href="/search/build.xml/1.htm">build.xml</a>
                                    <div>1,什么是antant是构建工具2,什么是构建概念到处可查到,形象来说,你要把代码从某个地方拿来,编译,再拷贝到某个地方去等等操作,当然不仅与此,但是主要用来干这个3,ant的好处跨平台   --因为ant是使用java实现的,所以它跨平台使用简单--与ant的兄弟make比起来语法清晰--同样是和make相比功能强大--ant能做的事情很多,可能你用了很久,你仍然不知道它能有</div>
                                </li>
                                <li><a href="/article/1255.htm"
                                       title="android按钮监听器的四种技术" target="_blank">android按钮监听器的四种技术</a>
                                    <span class="text-muted">百合不是茶</span>
<a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/xml%E9%85%8D%E7%BD%AE/1.htm">xml配置</a><a class="tag" taget="_blank" href="/search/%E7%9B%91%E5%90%AC%E5%99%A8/1.htm">监听器</a><a class="tag" taget="_blank" href="/search/%E5%AE%9E%E7%8E%B0%E6%8E%A5%E5%8F%A3/1.htm">实现接口</a>
                                    <div>android开发中经常会用到各种各样的监听器,android监听器的写法与java又有不同的地方;  
  
1,activity中使用内部类实现接口 ,创建内部类实例  使用add方法  与java类似 
  
创建监听器的实例 
myLis lis = new myLis(); 
  
使用add方法给按钮添加监听器 
 </div>
                                </li>
                                <li><a href="/article/1382.htm"
                                       title="软件架构师不等同于资深程序员" target="_blank">软件架构师不等同于资深程序员</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E5%B8%88/1.htm">架构师</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/1.htm">架构设计</a>
                                    <div>        本文的作者Armel Nene是ETAPIX Global公司的首席架构师,他居住在伦敦,他参与过的开源项目包括 Apache Lucene,,Apache Nutch, Liferay 和 Pentaho等。 
        如今很多的公司</div>
                                </li>
                                <li><a href="/article/1509.htm"
                                       title="TeamForge Wiki Syntax & CollabNet User Information Center" target="_blank">TeamForge Wiki Syntax & CollabNet User Information Center</a>
                                    <span class="text-muted">sunjing</span>
<a class="tag" taget="_blank" href="/search/TeamForge/1.htm">TeamForge</a><a class="tag" taget="_blank" href="/search/How+do/1.htm">How do</a><a class="tag" taget="_blank" href="/search/Attachement/1.htm">Attachement</a><a class="tag" taget="_blank" href="/search/Anchor/1.htm">Anchor</a><a class="tag" taget="_blank" href="/search/Wiki+Syntax/1.htm">Wiki Syntax</a>
                                    <div>the CollabNet user information center http://help.collab.net/ 
  
How do I create a new Wiki page? 
A CollabNet TeamForge project can have any number of Wiki pages. All Wiki pages are linked, and</div>
                                </li>
                                <li><a href="/article/1636.htm"
                                       title="【Redis四】Redis数据类型" target="_blank">【Redis四】Redis数据类型</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a>
                                    <div>概述 
Redis是一个高性能的数据结构服务器,称之为数据结构服务器的原因是,它提供了丰富的数据类型以满足不同的应用场景,本文对Redis的数据类型以及对这些类型可能的操作进行总结。 
Redis常用的数据类型包括string、set、list、hash以及sorted set.Redis本身是K/V系统,这里的数据类型指的是value的类型,而不是key的类型,key的类型只有一种即string</div>
                                </li>
                                <li><a href="/article/1763.htm"
                                       title="SSH2整合-附源码" target="_blank">SSH2整合-附源码</a>
                                    <span class="text-muted">白糖_</span>
<a class="tag" taget="_blank" href="/search/eclipse/1.htm">eclipse</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/tomcat/1.htm">tomcat</a><a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a><a class="tag" taget="_blank" href="/search/Google/1.htm">Google</a>
                                    <div>今天用eclipse终于整合出了struts2+hibernate+spring框架。 
我创建的是tomcat项目,需要有tomcat插件。导入项目以后,鼠标右键选择属性,然后再找到“tomcat”项,勾选一下“Is a tomcat project”即可。具体方法见源码里的jsp图片,sql也在源码里。 
  
  
补充1:项目中部分jar包不是最新版的,可能导</div>
                                </li>
                                <li><a href="/article/1890.htm"
                                       title="[转]开源项目代码的学习方法" target="_blank">[转]开源项目代码的学习方法</a>
                                    <span class="text-muted">braveCS</span>
<a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95/1.htm">学习方法</a>
                                    <div>转自: 
http://blog.sina.com.cn/s/blog_693458530100lk5m.html 
http://www.cnblogs.com/west-link/archive/2011/06/07/2074466.html 
  
1)阅读features。以此来搞清楚该项目有哪些特性2)思考。想想如果自己来做有这些features的项目该如何构架3)下载并安装d</div>
                                </li>
                                <li><a href="/article/2017.htm"
                                       title="编程之美-子数组的最大和(二维)" target="_blank">编程之美-子数组的最大和(二维)</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%BE%8E/1.htm">编程之美</a>
                                    <div>package beautyOfCoding;

import java.util.Arrays;
import java.util.Random;

public class MaxSubArraySum2 {

	/**
	 * 编程之美 子数组之和的最大值(二维)
	 */
	private static final int ROW = 5;
	private stat</div>
                                </li>
                                <li><a href="/article/2144.htm"
                                       title="读书笔记-3" target="_blank">读书笔记-3</a>
                                    <span class="text-muted">chengxuyuancsdn</span>
<a class="tag" taget="_blank" href="/search/jquery%E7%AC%94%E8%AE%B0/1.htm">jquery笔记</a><a class="tag" taget="_blank" href="/search/resultMap%E9%85%8D%E7%BD%AE/1.htm">resultMap配置</a><a class="tag" taget="_blank" href="/search/ibatis%E4%B8%80%E5%AF%B9%E5%A4%9A%E9%85%8D%E7%BD%AE/1.htm">ibatis一对多配置</a>
                                    <div>1、resultMap配置 
2、ibatis一对多配置 
3、jquery笔记 
 
1、resultMap配置
当<select resultMap="topic_data">
<resultMap id="topic_data">必须一一对应。
(1)<resultMap class="tblTopic&q</div>
                                </li>
                                <li><a href="/article/2271.htm"
                                       title="[物理与天文]物理学新进展" target="_blank">[物理与天文]物理学新进展</a>
                                    <span class="text-muted">comsci</span>

                                    <div> 
 
      如果我们必须获得某种地球上没有的矿石,才能够进行某些能量输出装置的设计和建造,而要获得这种矿石,又必须首先进行深空探测,而要进行深空探测,又必须获得这种能量输出装置,这个矛盾的循环,会导致地球联盟在与宇宙文明建立关系的时候,陷入困境 
 
      怎么办呢? 
 
 </div>
                                </li>
                                <li><a href="/article/2398.htm"
                                       title="Oracle 11g新特性:Automatic Diagnostic Repository" target="_blank">Oracle 11g新特性:Automatic Diagnostic Repository</a>
                                    <span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/ADR/1.htm">ADR</a>
                                    <div>Oracle Database 11g的FDI(Fault Diagnosability Infrastructure)是自动化诊断方面的又一增强。 
FDI的一个关键组件是自动诊断库(Automatic Diagnostic Repository-ADR)。 
 
在oracle 11g中,alert文件的信息是以xml的文件格式存在的,另外提供了普通文本格式的alert文件。 
这两份log文</div>
                                </li>
                                <li><a href="/article/2525.htm"
                                       title="简单排序:选择排序" target="_blank">简单排序:选择排序</a>
                                    <span class="text-muted">dieslrae</span>
<a class="tag" taget="_blank" href="/search/%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F/1.htm">选择排序</a>
                                    <div>
    public void selectSort(int[] array){
        int select;
        
        for(int i=0;i<array.length;i++){
            select = i;
            
            for(int k=i+1;k<array.leng</div>
                                </li>
                                <li><a href="/article/2652.htm"
                                       title="C语言学习六指针的经典程序,互换两个数字" target="_blank">C语言学习六指针的经典程序,互换两个数字</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/c/1.htm">c</a>
                                    <div>示例程序,swap_1和swap_2都是错误的,推理从1开始推到2,2没完成,推到3就完成了 
# include <stdio.h>

void swap_1(int, int);
void swap_2(int *, int *);
void swap_3(int *, int *);

int main(void)
{
	int a = 3;
	int b = </div>
                                </li>
                                <li><a href="/article/2779.htm"
                                       title="php 5.4中php-fpm 的重启、终止操作命令" target="_blank">php 5.4中php-fpm 的重启、终止操作命令</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a>
                                    <div>php 5.4中php-fpm 的重启、终止操作命令: 
查看php运行目录命令:which php/usr/bin/php 
查看php-fpm进程数:ps aux | grep -c php-fpm 
查看运行内存/usr/bin/php  -i|grep mem 
重启php-fpm/etc/init.d/php-fpm restart 
在phpinfo()输出内容可以看到php</div>
                                </li>
                                <li><a href="/article/2906.htm"
                                       title="线程同步工具类" target="_blank">线程同步工具类</a>
                                    <span class="text-muted">shuizhaosi888</span>
<a class="tag" taget="_blank" href="/search/%E5%90%8C%E6%AD%A5%E5%B7%A5%E5%85%B7%E7%B1%BB/1.htm">同步工具类</a>
                                    <div>同步工具类包括信号量(Semaphore)、栅栏(barrier)、闭锁(CountDownLatch) 
  
闭锁(CountDownLatch) 
public class RunMain {
	public long timeTasks(int nThreads, final Runnable task) throws InterruptedException {
		fin</div>
                                </li>
                                <li><a href="/article/3033.htm"
                                       title="bleeding edge是什么意思" target="_blank">bleeding edge是什么意思</a>
                                    <span class="text-muted">haojinghua</span>
<a class="tag" taget="_blank" href="/search/DI/1.htm">DI</a>
                                    <div>不止一次,看到很多讲技术的文章里面出现过这个词语。今天终于弄懂了——通过朋友给的浏览软件,上了wiki。  
我再一次感到,没有辞典能像WiKi一样,给出这样体贴人心、一清二楚的解释了。为了表达我对WiKi的喜爱,只好在此一一中英对照,给大家上次课。 
  
In computer science, bleeding edge is a term that </div>
                                </li>
                                <li><a href="/article/3160.htm"
                                       title="c中实现utf8和gbk的互转" target="_blank">c中实现utf8和gbk的互转</a>
                                    <span class="text-muted">jimmee</span>
<a class="tag" taget="_blank" href="/search/c/1.htm">c</a><a class="tag" taget="_blank" href="/search/iconv/1.htm">iconv</a><a class="tag" taget="_blank" href="/search/utf8%26gbk%E7%BC%96%E7%A0%81/1.htm">utf8&gbk编码</a>
                                    <div>#include <iconv.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>

int code_c</div>
                                </li>
                                <li><a href="/article/3287.htm"
                                       title="大型分布式网站架构设计与实践" target="_blank">大型分布式网站架构设计与实践</a>
                                    <span class="text-muted">lilin530</span>
<a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a><a class="tag" taget="_blank" href="/search/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E/1.htm">搜索引擎</a>
                                    <div>1.大型网站软件系统的特点? 
a.高并发,大流量。 
b.高可用。 
c.海量数据。 
d.用户分布广泛,网络情况复杂。 
e.安全环境恶劣。 
f.需求快速变更,发布频繁。 
g.渐进式发展。 
 
2.大型网站架构演化发展历程? 
a.初始阶段的网站架构。 
应用程序,数据库,文件等所有的资源都在一台服务器上。 
b.应用服务器和数据服务器分离。 
c.使用缓存改善网站性能。 
d.使用应用</div>
                                </li>
                                <li><a href="/article/3414.htm"
                                       title="在代码中获取Android theme中的attr属性值" target="_blank">在代码中获取Android theme中的attr属性值</a>
                                    <span class="text-muted">OliveExcel</span>
<a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/theme/1.htm">theme</a>
                                    <div>Android的Theme是由各种attr组合而成, 每个attr对应了这个属性的一个引用, 这个引用又可以是各种东西. 
  
在某些情况下, 我们需要获取非自定义的主题下某个属性的内容 (比如拿到系统默认的配色colorAccent), 操作方式举例一则: 
int defaultColor = 0xFF000000;
int[] attrsArray = { andorid.r.</div>
                                </li>
                                <li><a href="/article/3541.htm"
                                       title="基于Zookeeper的分布式共享锁" target="_blank">基于Zookeeper的分布式共享锁</a>
                                    <span class="text-muted">roadrunners</span>
<a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a><a class="tag" taget="_blank" href="/search/%E5%85%B1%E4%BA%AB%E9%94%81/1.htm">共享锁</a>
                                    <div>首先,说说我们的场景,订单服务是做成集群的,当两个以上结点同时收到一个相同订单的创建指令,这时并发就产生了,系统就会重复创建订单。等等......场景。这时,分布式共享锁就闪亮登场了。 
  
共享锁在同一个进程中是很容易实现的,但在跨进程或者在不同Server之间就不好实现了。Zookeeper就很容易实现。具体的实现原理官网和其它网站也有翻译,这里就不在赘述了。 
  
官</div>
                                </li>
                                <li><a href="/article/3668.htm"
                                       title="两个容易被忽略的MySQL知识" target="_blank">两个容易被忽略的MySQL知识</a>
                                    <span class="text-muted">tomcat_oracle</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div>1、varchar(5)可以存储多少个汉字,多少个字母数字?     相信有好多人应该跟我一样,对这个已经很熟悉了,根据经验我们能很快的做出决定,比如说用varchar(200)去存储url等等,但是,即使你用了很多次也很熟悉了,也有可能对上面的问题做出错误的回答。     这个问题我查了好多资料,有的人说是可以存储5个字符,2.5个汉字(每个汉字占用两个字节的话),有的人说这个要区分版本,5.0</div>
                                </li>
                                <li><a href="/article/3795.htm"
                                       title="zoj 3827 Information Entropy(水题)" target="_blank">zoj 3827 Information Entropy(水题)</a>
                                    <span class="text-muted">阿尔萨斯</span>
<a class="tag" taget="_blank" href="/search/format/1.htm">format</a>
                                    <div> 题目链接:zoj 3827 Information Entropy 
 题目大意:三种底,计算和。 
 解题思路:调用库函数就可以直接算了,不过要注意Pi = 0的时候,不过它题目里居然也讲了。。。limp→0+plogb(p)=0,因为p是logp的高阶。 
#include <cstdio>
#include <cstring>
#include <cmath&</div>
                                </li>
                </ul>
            </div>
        </div>
    </div>

<div>
    <div class="container">
        <div class="indexes">
            <strong>按字母分类:</strong>
            <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
        </div>
    </div>
</div>
<footer id="footer" class="mb30 mt30">
    <div class="container">
        <div class="footBglm">
            <a target="_blank" href="/">首页</a> -
            <a target="_blank" href="/custom/about.htm">关于我们</a> -
            <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
            <a target="_blank" href="/sitemap.txt">Sitemap</a> -
            <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
        </div>
        <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
        </div>
    </div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>





</body>

</html>