内容简介:一千个观众就有一千个哈姆雷特。你在网络上可以找到上百万个有关如何配置 Webpack 的教程,所以,你可能已经看到了一千种不同的配置方法。Webpack 本身在快速演化,除此之外,还有很多加载器和插件紧随其后。这就是为什么这些配置文件会各有不同:组合使用同一组工具的不同版本可能会奏效,也可能不能如愿。很多人一直在抱怨 Webpack 使用起来很麻烦。从某些方面来看,确实如此。但是,我不得不说,从我使用 gulp 和 grunt 的经验来看,它们也存在同样的问题。也就是说,当你使用 npm 模块时,就不可避免
一千个观众就有一千个哈姆雷特。你在网络上可以找到上百万个有关如何配置 Webpack 的教程,所以,你可能已经看到了一千种不同的配置方法。Webpack 本身在快速演化,除此之外,还有很多加载器和插件紧随其后。这就是为什么这些配置文件会各有不同:组合使用同一组 工具 的不同版本可能会奏效,也可能不能如愿。
很多人一直在抱怨 Webpack 使用起来很麻烦。从某些方面来看,确实如此。但是,我不得不说,从我使用 gulp 和 grunt 的经验来看,它们也存在同样的问题。也就是说,当你使用 npm 模块时,就不可避免地会出现某些模块版本不兼容的问题。
到目前为止,Webpack 4 是最流行的模块捆绑器之一。它提供了很多新特性,例如零配置、合理的默认值、性能改进、开箱即用的优化工具,等等。
零配置:Webpack 4 不需要配置文件,这是 Webpack 4 的一个全新的变更。
性能提升:Webpack 4 是迄今为止最快的 Webpack 版本。
合理的默认值:Webpack 4 的主要概念包括入口、输出、加载器和插件。
核心概念
入口
它应该是一个.js 文件,人们会在这个文件中包含.scss 或.css 文件,这样做可能会导致很多意外的错误。有时候你可能会看到一个入口包含了几个.js 文件。虽然有时候你可以这么做,但它通常会增加更多的复杂性。
输出
这是 build/ 或 dist/ 或任意名称的文件夹,用于存放最终的.js 文件。
加载器
它们主要用来编译或转换你的代码,例如 postcss-loader。
插件
插件在将代码输出到文件方面起着至关重要的作用。
快速入门
创建一个新目录,并进入这个目录:
复制代码
mkdirwebpack-4-tutorial cdwebpack-4-tutorial
初始化 package.json:
复制代码
npminit
或者:
复制代码
yarn init
我们需要下载 Webpack 4 和 webpack-cli:
复制代码
npm install webpack webpack-cli --save-dev
或者:
复制代码
yarnaddwebpack webpack-cli--dev
现在,打开 package.json 文件,并添加一个构建脚本:
复制代码
"scripts": { "dev":"webpack" }
运行它,你可能会看到一个警告:
复制代码
WARNINGinconfiguration The ‘mode’optionhasnotbeenset, webpack will fallbackto‘production’forthisvalue.Set‘mode’optionto‘development’or‘production’toenabledefaultsforeachenvironment. You canalsosetitto‘none’todisableanydefaultbehavior. Learn more: https://webpack.js.org/concepts/mode/
Webpack 4 的模式
你需要编辑脚本,在其中包含模式标志:
复制代码
"scripts": { "dev": "webpack --mode development" } ERRORin Entry module not found: Error: Can’t resolve ‘./src’ in ‘~/webpack-4-quickstart’
Webpack 会查找一个带有 index.js 文件的文件夹.src/。这是 Webpack 4 的默认行为,因为它是零配置的。
让我们创建一个带有 index.js 文件的目录./src,并这个文件中加一些代码。
复制代码
console.log("hello, world");
现在运行脚本:
复制代码
npmrundev
或者:
复制代码
yarn dev
如果一切正常,你将得到一个./dist/main.js 文件。好了,代码已经编译好了。但刚刚都发生了什么?
默认情况下,Webpack 是零配置的,所以你不需要配置 webpack.config.js。因此,它必须假设一些默认行为,它总是先查找./src 文件夹,然后在其中查找 index.js,并将输出写入./dist/main.js 文件。
如果你遇到这个错误:
复制代码
ERROR in ./node_modules/fsevents/node_modules/node-pre-gyp/lib/publish.js Module notfound:Error:Can't resolve 'aws-sdk' in '/Users/mobr/Documents/workshop/test-webpack-4-setup/node_modules/fsevents/node_modules/node-pre-gyp/lib'
这里 描述了更多细节。要解决这个问题,你需要创建 webpack.config.js 文件,然后按照本文后面的教程配置这个文件。但是首先你需要下载 webpack-node-externals 。
复制代码
npm install webpack-node-externals--save-dev
或者:
复制代码
yarn add webpack-node-externals--dev
然后导入这个模块:
复制代码
const nodeExternals = require('webpack-node-externals'); ... module.exports = { ... target: 'node', externals: [nodeExternals()], ... };
拥有 2 个配置文件是 Webpack 的常见做法,尤其是在大型项目中,通常一个用于开发,一个用于生产环境。Webpack 4 提供了两种模式:生产(production)和开发(development)。这样可以避免使用两个文件(对于中型项目)。
复制代码
"scripts": { "dev":"webpack --mode development", "build":"webpack --mode production" }
如果你细心一点就会发现,main.js 文件并没有被最小化。
我将在示例中使用 build 脚本,因为它提供了很多开箱即用的优化措施,但其实你可以随意使用它们中的任何一个。build 和 dev 脚本之间最主要的区别在于它们如何输出文件。build 用于创建用于生产环境的代码,而 dev 用于开发环境,所以它支持热模块替换、开发服务器以及其他很多有助于开发工作的东西。
你可以覆盖 npm 脚本中的默认值,只需使用标志:
复制代码
"scripts": { "dev":"webpack --mode development ./src/index.js --output ./dist/main.js", "build":"webpack --mode production ./src/index.js --output ./dist/main.js" }
这将覆盖默认选项,而无需配置任何东西。
作为练习,也可以试一试这些标志:
–watch 标志用于启用监听模式。它将监控你的文件更改,并在每次文件发生更新时重新编译文件。
复制代码
"scripts":{ "dev":"webpack--modedevelopment./src/index.js--output./dist/main.js--watch", "build":"webpack--modeproduction./src/index.js--output./dist/main.js--watch" }
–entry 标志与–output 标志差不多,但会重写入口路径。
转换.js 代码
现代 JS 代码主要是用 ES6 编写的,但并非所有浏览器都支持 ES6。因此,你需要对代码进行转换——将 ES6 代码转换为 ES5。你可以使用 babel——现在最流行的工具。当然,我们不仅可以转换 ES6 代码,也可以转换其他 JS 实现,如 TypeScript、React,等等。
复制代码
npminstallbabel-corebabel-loaderbabel-preset-env--save-dev
或者:
复制代码
yarnaddbabel-corebabel-loaderbabel-preset-env--dev
为 babel 创建配置文件.babelrc,并在文件中粘贴以下内容。
复制代码
{ "presets": [ "env" ] }
我们有两个配置 babel-loader 的方式:
-
使用配置文件 Webpack.config.js
-
在 npm 脚本中使用–module-bind
从技术上说,你可以通过 Webpack 引入的新标志做很多事情,但为简单起见,我选择了 webpack.config.js。
配置文件
虽然 Webpack 宣称自己是零配置的,但这种零配置主要还是适用于默认设置,比如入口和输出。
我们将创建包含以下内容的 webpack.config.js:
复制代码
// webpack v4 constpath =require('path'); // update from 23.12.2018 constnodeExternals =require('webpack-node-externals'); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'main.js' }, target:'node',// update from 23.12.2018 externals: [nodeExternals()],// update from 23.12.2018 module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } } ] } };
从 npm 脚本中移除标志。
复制代码
"scripts": { "build":"webpack --mode production", "dev":"webpack --mode development" },
现在,当我们运行 npm run build 或 yarn build 时,它应该会在./dist/main.js 中生成一个最小化的.js 文件。如果没有,请尝试重新安装 babel-loader。
如果遇到模块“@babel/core”冲突,说明某些预加载的 babel 依赖项不兼容。我遇到的错误是:
复制代码
Module build failed: Error: Cannot find module'@babel/core' babel-loader@8requires Babel7.x (the package'@babel/core').Ifyou'd like to use Babel 6.x ('babel-core'), you should install 'babel-loader@7'.
我是这样解决的:
复制代码
yarnadd@babel/core--dev
HTML 和 CSS 导入
我们先在./dist 文件夹中创建 index.html 文件。
复制代码
<html> <head> <linkrel="stylesheet"href="style.css"> </head> <body> <div>Hello, world!</div> <scriptsrc="main.js"></script> </body> </html>
我们在这里导入了 style.css,现在让我们来配置它!正如我们所说,我们只有一个 Webpack 入口点。那么应该将 css 文件放在哪里?在./src 文件夹中创建 style.css 文件。
复制代码
div{ color: red; }
不要忘了将它包含在.js 文件中:
复制代码
import"./style.css"; console.log("hello, world");
在 Webpack 中为 css 文件创建一个新规则:
复制代码
// webpack v4 constpath =require('path'); // update from 23.12.2018 constnodeExternals =require('webpack-node-externals'); constExtractTextPlugin =require('extract-text-webpack-plugin'); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'main.js' }, target:'node',// update from 23.12.2018 externals: [nodeExternals()],// update from 23.12.2018 module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } }, { test:/\.css$/, use: ExtractTextPlugin.extract( { fallback:'style-loader', use: ['css-loader'] }) } ] } };
在终端中运行:
复制代码
npminstallextract-text-webpack-plugin--save-dev npminstallstyle-loader css-loader--save-dev
或者:
复制代码
yarnaddextract-text-webpack-plugin style-loader css-loader--dev
我们需要使用 extract-text-webpack-plugin 来编译我们的.css。但是在 Webpack 4 中使用这个插件有点问题,可能会遇到这个 错误 。
要修复这个问题,需要运行:
复制代码
npminstall-Dextract-text-webpack-plugin@next
或者:
复制代码
yarnadd--dev extract-text-webpack-plugin@next
然后你的 css 代码应该被编译为./dist/style.css。
到了这个时候,我的 package.json 的 dev 依赖项看起来像这样:
复制代码
"devDependencies": { "babel-core":"^6.26.0", "babel-loader":"^7.1.4", "babel-preset-env":"^1.6.1", "css-loader":"^0.28.11", "extract-text-webpack-plugin":"^4.0.0-beta.0", "style-loader":"^0.20.3", "webpack":"^4.4.1", "webpack-cli":"^2.0.12" }
请注意,另一种组合可能无法正常运行,因为即使是将 webpack-cli 2.0.12 更新为 2.0.13 也可能会带来问题。
现在它应该将 style.css 输出到./dist 文件夹中了。
Mini-CSS 插件
Mini-CSS 插件旨在取代 extract-text 插件,并为你提供更好的兼容性。我重新修改了我的 Webpack 文件,使用 mini-css-extract-plugin 来编译 style.css。
复制代码
npminstallmini-css-extract-plugin--save-dev
或者:
复制代码
yarnaddmini-css-extract-plugin --dev
以及:
复制代码
// webpack v4 constpath =require('path'); // update from 23.12.2018 constnodeExternals =require('webpack-node-externals'); // const ExtractTextPlugin = require('extract-text-webpack-plugin'); constMiniCssExtractPlugin =require("mini-css-extract-plugin"); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'[name].[chunkhash].js' }, target:'node',// update from 23.12.2018 externals: [nodeExternals()],// update from 23.12.2018 module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } }, { test:/\.css$/, use: [ 'style-loader', MiniCssExtractPlugin.loader,'css-loader'] } ] }, plugins: [ newMiniCssExtractPlugin({ filename:'style.css', }) ] };
我们需要使用 MiniCssExtractPlugin,因为默认情况下 Webpack 只能识别.js 格式。MiniCssExtractPlugin 将.css 内容提取到./dist 目录下不同的.css 文件中。
配置对 SCSS 的支持
使用 SASS 和 POSTCSS 开发网站已经非常普遍,因此,我们将首先包括对 SASS 的支持。让我们重命名./src/style.css 文件,并创建另一个文件夹来存放.scss 文件。现在我们需要添加对.scss 格式的支持。
复制代码
npm installnode-sasssass-loader --save-dev
或者:
复制代码
yarn addnode-sasssass-loader --dev
使用./scss/main.scss 替换 style.css,并修改 test 配置,以便支持.scss:
复制代码
// webpack v4 constpath =require('path'); // update 23.12.2018 constnodeExternals =require('webpack-node-externals'); constMiniCssExtractPlugin =require("mini-css-extract-plugin"); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'main.js' }, target:"node",// update 23.12.2018 externals: [nodeExternals()],// update 23.12.2018 module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } }, { test:/\.scss$/, use: [ "style-loader", MiniCssExtractPlugin.loader, "css-loader", "sass-loader" ] } ] } ...
HTML 模板
现在让我们来创建.html 文件模板。将以下内容添加到./src 目录的 index.html 文件中。
复制代码
<html> <head> <linkrel="stylesheet"href="style.css"> </head> <body> <div>Hello, world!</div> <scriptsrc="main.js"></script> </body> </html>
我们需要借助 html 插件才能将这个文件作为模板使用。
复制代码
npminstallhtml-webpack-plugin--save-dev
或者:
复制代码
yarnaddhtml-webpack-plugin --dev
将其添加到你的 Webpack 文件中:
复制代码
// webpack v4 constpath =require('path'); // update 23.12.2018 constnodeExternals =require('webpack-node-externals'); constMiniCssExtractPlugin =require("mini-css-extract-plugin"); constHtmlWebpackPlugin =require('html-webpack-plugin'); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'main.js' }, target:"node",// update 23.12.2018 externals: [nodeExternals()],// update 23.12.2018 module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } }, { test:/\.scss$/, use: [ "style-loader", MiniCssExtractPlugin.loader, "css-loader", "sass-loader" ] } ] }, plugins: [ newMiniCssExtractPlugin({ filename:"style.css" }), newHtmlWebpackPlugin({ inject:false, hash:true, template:'./src/index.html', filename:'index.html' }) ] };
现在./src/index.html 文件就变成了一个模板。现在删除./dist 文件夹其其中的所有文件,然后重新构建,看看是不是一切正常。
复制代码
rm -rf ./dist npmrundev
或者:
复制代码
rm-rf ./dist yarndev
你会看到./dist 文件夹重新生成,其中包含了三个文件:index.html、style.css 和 main.js.
缓存和哈希
开发中最常见的问题之一是如何实现缓存。因为这篇文章主要是关于如何配置 Webpack,所以不会专注于介绍缓存的实现细节。我只想说,解决缓存问题最常用的方法之一是在文件中(例如 style.css 和 script.js)添加一个哈希值。你可以参考 这篇文章 。
使用哈希以后,浏览器只会请求发生变更的文件。
Webpack 4 基于 chunkhash 实现了的内置的哈希功能。修改 Webpack 文件:
复制代码
// webpack v4 constpath =require('path'); // update 23.12.2018 constnodeExternals =require("webpack-node-externals"); constMiniCssExtractPlugin =require("mini-css-extract-plugin"); constHtmlWebpackPlugin =require('html-webpack-plugin'); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'[name].[chunkhash].js' }, target:"node", externals: [nodeExternals()], module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } }, { test:/\.scss$/, use: [ "style-loader", MiniCssExtractPlugin.loader, "css-loader", "sass-loader" ] } ] }, plugins: [ newMiniCssExtractPlugin({ filename:"style.[contenthash].css" }), newHtmlWebpackPlugin({ inject:false, hash:true, template:'./src/index.html', filename:'index.html' }) ] };
在./src/index.html 文件中添加:
复制代码
<html> <head> <linkrel="stylesheet"href="<%=htmlWebpackPlugin.files.chunks.main.css %>"> </head> <body> <div>Hello, world!</div> <scriptsrc="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script> </body> </html>
我们将使用 htmlWebpackPlugin.files.chunks.main 模式生成哈希。看一下./dist 目录下的 index.html 文件:
如果我们在不修改.js 和.css 文件的情况下运行 npm run dev,不管运行多少次,两个文件中的哈希值都应该是一样的。
CSS 的哈希问题以及如何解决
如果你在 Webpack 4 中使用了 ExtractTextPlugin,可能会存在这个问题。如果你使用的是 MiniCssExtractPlugin,这个问题应该就不会发生。
我们的解决方案还不够完美。如果我们修改了.scss 文件中的某些代码会怎样?你会发现,现在不生成新的哈希了。如果我们在.js 文件中增加一行 console.log,比如:
复制代码
import"./style.css"; console.log("hello, world"); console.log("Hello, world 2");
再次运行 dev 脚本,你将看到两个文件中的哈希值已更新。
这个问题是已知的,Stack Overflow 上已经讨论过 这个问题 。
那么应该怎么解决这个问题?
在尝试了很多声称可以解决这个问题的插件后,我终于找到了两个可行的解决方案。
解决方案 1
可能还存在一些冲突,可以试试 mini-css-extract 插件。
解决方案 2
在 CSS Extract 插件中使用 [hash] 替换 [chukhash],但这似乎会与 Webpack 4.3 提供的 [contenthash] 变量产生冲突,所以可以结合使用这个插件: webpack-md5-hash 。
现在再测试就会发现两个文件的哈希都会更新。
JS 的哈希问题以及如何解决?
如果你使用了 MiniCssExtractPlugin,可能会遇到另一个问题:每次修改 SCSS 中的某些内容时,.js 文件和.css 输出文件的哈希都会被更新。
解决方案:
使用 webpack-md5-hash 插件。如果你修改了 main.scss 文件并运行 dev 脚本,应该只有新的 style.css 文件里会包含新的哈希,而不是两个文件都会这样。
复制代码
// webpack v4 constpath =require('path'); // update 23.12.2018 constnodeExternals =require("webpack-node-externals"); constMiniCssExtractPlugin =require("mini-css-extract-plugin"); constHtmlWebpackPlugin =require("html-webpack-plugin"); constWebpackMd5Hash =require("webpack-md5-hash"); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'[name].[chunkhash].js' }, target:"node",// update 23.12.2018 externals: [nodeExternals()],// update 23.12.2018 module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } }, { test:/\.scss$/, use: ExtractTextPlugin.extract( { fallback:'style-loader', use: ['css-loader','sass-loader'] }) } ] }, plugins: [ newMiniCssExtractPlugin({ filename:"style.[contenthash].css" }), newHtmlWebpackPlugin({ inject:false, hash:true, template:"./src/index.html", filename:"index.html" }), newWebpackMd5Hash() ] };
集成 PostCSS
为了让输出的.css 更进一步,我们可以加入 PostCSS 。
PostCSS 提供了 autoprefixer、cssnano 和其他好用的东西。我每天都在用它。我们需要安装 postcss-loader,还有 autoprefixer,因为稍后会用到它。
复制代码
npminstall postcss-loader --save-dev npmi -D autoprefixer
或者:
复制代码
yarnaddpostcss-loader autoprefixer --dev
创建 postcss.config.js,并粘贴以下内容:
复制代码
module.exports = { plugins: [ require('autoprefixer') ] }
我们的 Webpack.config.js 现在应该是这样的:
复制代码
// webpack v4 constpath =require('path'); // update 23.12.2018 constnodeExternals =require("webpack-node-externals"); constMiniCssExtractPlugin =require("mini-css-extract-plugin"); constHtmlWebpackPlugin =require("html-webpack-plugin"); constWebpackMd5Hash =require("webpack-md5-hash"); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'[name].[chunkhash].js' }, target:"node", externals: [nodeExternals()], module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } }, { test:/\.scss$/, use: [ 'style-loader', MiniCssExtractPlugin.loader,'css-loader','postcss-loader','sass-loader'] } ] }, plugins: [ newMiniCssExtractPlugin({ filename:'style.[contenthash].css', }), newHtmlWebpackPlugin({ inject:false, hash:true, template:'./src/index.html', filename:'index.html' }), newWebpackMd5Hash() ] };
请注意插件的顺序:
复制代码
use: ['style-loader',MiniCssExtractPlugin.loader,'css-loader','postcss-loader','sass-loader']
加载器按照从尾到头的顺序使用插件。
你可以向.scss 文件中添加更多内容并检查输出,以此来测试 autoprefixer 。
你也可以在.browserslistrc 文件中指定要支持的浏览器来调整输出的内容。
你可以在这个 网站 上了解更多 PostCSS 可用的插件,例如:
我使用 cssnano 来最小化输出文件,并用 css-mqpacker 来处理媒体查询。
也有人说可以试试 cleancss。
保持整洁
在重新生成文件之前,我们可以尝试使用 clean-Webpack-plugin 来清理./dist 文件夹。
复制代码
// webpack v4 constpath =require('path'); // update 23.12.2018 constnodeExternals =require("webpack-node-externals"); constMiniCssExtractPlugin =require("mini-css-extract-plugin"); constHtmlWebpackPlugin =require("html-webpack-plugin"); constWebpackMd5Hash =require("webpack-md5-hash"); constCleanWebpackPlugin =require('clean-webpack-plugin'); module.exports = { entry: { main:'./src/index.js'}, output: { path: path.resolve(__dirname,'dist'), filename:'[name].[chunkhash].js' }, target:"node", externals: [nodeExternals()], module: { rules: [ { test:/\.js$/, exclude:/node_modules/, use: { loader:"babel-loader" } }, { test:/\.scss$/, use: [ 'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] } ] }, plugins: [ newCleanWebpackPlugin('dist', {} ), newMiniCssExtractPlugin({ filename:'style.[contenthash].css', }), newHtmlWebpackPlugin({ inject:false, hash:true, template:'./src/index.html', filename:'index.html' }), newWebpackMd5Hash() ] };
带有最新版本插件的 package.json 看起来是这样的:
复制代码
{ “name”: “webpack-test”, “version”: “1.0.0”, “description”: “”, “main”: “index.js”, “scripts”: { “build”: “webpack--mode production”, “dev”: “webpack--mode development” }, “author”: “”, “license”: “ISC”, "devDependencies": { "@babel/core": "^7.2.2", "autoprefixer": "^9.4.3", "babel-core": "^6.26.3", "babel-loader": "^8.0.4", "babel-preset-env": "^1.7.0", "css-loader": "^2.0.2", "html-webpack-plugin": "^3.2.0", "mini-css-extract-plugin": "^0.5.0", "node-sass": "^4.11.0", "postcss-loader": "^3.0.0", "sass-loader": "^7.1.0", "style-loader": "^0.23.1", "webpack": "4.28", "webpack-cli": "^3.1.2" }, "dependencies": { "clean-webpack-plugin": "^1.0.0", "webpack-md5-hash": "^0.0.6", "webpack-node-externals": "^1.7.2" } }
英文原文:
更多内容,请关注前端之巅(ID:frontshow)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用 AJP 方式配置反向代理
- webpack4 正确的配置方式
- 配置 Tomcat 以服务方式自动运行
- SpringBoot优雅的配置拦截器方式
- Spring Boot 2 实战:常用读取配置的方式
- Nuxt+Express后端api接口配置与实现方式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
我用微软改变世界
保罗·艾伦 / 吴果锦 / 浙江人民出版社 / 2012-3 / 46.00元
《我用微软改变世界(微软联合创始人保罗•艾伦回忆录)》内容简介:1975年,两个从大学退学的男孩夜以继日地设计一款软件。其中一个男孩就是后来的世界首富比尔盖茨,而另外一个则作为盖茨背后的男人,一直生活在盖茨的阴影里,其实,他的人生经历远比盖茨更为传奇和丰富。 16岁,与比尔盖茨在顶级名校湖畔中学相遇,成为最佳拍档,无数趣事,无数闹腾,高呼“处男万岁”还不够,还得意扬扬把这话刻在碑上留给学弟们......一起来看看 《我用微软改变世界》 这本书的介绍吧!