【Webpack】319- Webpack4 入门手册(共 18 章)(上)


介绍

1. 背景

最近和部门老大,一起在研究团队【EFT - 前端新手村】的建设,目的在于:帮助新人快速了解和融入公司团队帮助零基础新人学习和入门前端开发并且达到公司业务开发水平

本文也是属于【EFT - 前端新手村】的一部分,用来帮助新人快速入门 Webpack4,内容偏基础,当然也可以作为复习材料~~这里分享给各位小伙伴啦!

2. 文章概要

由于本文篇幅较长,将分为《Webpack4入门手册(上)(共 18 章)》和《Webpack4入门手册(下)(共 18 章)》两篇文章发布,请联系起来看~

我将从最基础的【项目初始化】开始介绍,到【处理 CSS / JS / 图片】,到【热更新,打包优化】等等,一一介绍和实践。

文章共分为 18 章,关于最基础的四个核心概念,可以到我整理的另一篇文章 《Webpack4 的四个核心概念》 中学习。

《Webpack4 的四个核心概念》 https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Webpack/guide/README.md

3. 教程目录

一、 项目初始化

1. 初始化 demo

新建并进入文件夹 leo:

  1. mkdir leo

  2. cd leo

然后本地安装 webpack 和 webpack-cli (在 Webpack 4.0以后需要单独安装):

  1. npm install webpack webpack-cli --save-dev

初始化项目结构:

  1. + ├─package.json

  2. + ├─dist // 存放最终打包的文件

  3. + │ └─index.html

  4. + ├─src // 存放入口文件等开发文件

  5. + │ └─index.js

  6. + ├─webpack.config.js // webpack的配置文件

安装 lodash

  1. npm install lodash --save-dev

--save 可以简写为 -S--save-dev可以简写为 -D.

开发 index.js

  1. import _ from 'lodash';


  2. function createElement(){

  3. let div = document.createElement('div');

  4. div.innerHTML = _.join(['my', 'name', 'is', 'leo'], '');

  5. return div;

  6. }

  7. document.body.appendChild(createElement());

开发 webpack.config.js

  1. const path = require('path');


  2. module.exports = {

  3. entry: './src/index.js',

  4. mode: 'development',

  5. output: {

  6. filename: 'main.js',

  7. path: path.resolve(__dirname, 'dist')

  8. }

  9. }

2. 打包测试

开始第一次打包任务:

  1. npx webpack


  2. // 输出:


  3. Hash: 030b37b6b9a0b4344437

  4. Version: webpack 4.39.1Time: 308ms

  5. Built at: 2019-08-0708:10:21

  6. AssetSizeChunksChunkNames

  7. main.js 552KiB main [emitted] main

  8. Entrypoint main = main.js

  9. [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built]

  10. [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {main} [built][./src/index.js] 225 bytes {main} [built]

  11. + 1 hidden module

打包成功后,生成的文件会保存在 dist 目录中。

现在在 dist/index.html 中引入打包后的 main.js,打开浏览器测试:

  1. <scriptsrc="./main.js"></script>

二、 webpack 处理 CSS 模块

这一部分,我们开始学着使用 webpack 去处理 css 相关的模块。

1. 修改代码

在项目 src 目录中,新建 style 文件夹,并新建 index.css 文件:

  1. ├─package.json

  2. ├─dist // 存放最终打包的文件

  3. │ └─index.html

  4. ├─src // 存放入口文件等开发文件

  5. │ ├─index.js

  6. + │ └─style

  7. + │ └─index.css

  8. ├─webpack.config.js // webpack的配置文件

接着在 index.js 的新建元素方法中,添加 class 为 box,这样新建的元素就带有 box 的 class属性:

  1. // src/index.js


  2. import _ from'lodash';

  3. import'./style/index.css';// 引入样式文件


  4. function createElement(){

  5. let div = document.createElement('div');

  6. div.innerHTML = _.join(['my', 'name', 'is', 'leo'], '');

  7. + div.className = 'box';

  8. return div;

  9. }

  10. document.body.appendChild(createElement());

然后在 index.css 文件为 box :

  1. // src/style/index.css


  2. .box{

  3. color: red;

  4. }

注意:

这里使用 import'./style/index.css'; 引入我们的样式文件,是没办法解析使用,这时我们需要在 webpack 中使用到第三方 loader 插件,这里我们使用:

  • css-loader :用于处理 css 文件,使得能在 js 文件中引入使用;

  • style-loader :用于将 css 文件注入到 index.html 中的 <style> 标签上;

2. 安装配置插件

安装插件:

  1. npm install --save-dev style-loader css-loader

再到 webpack.config.js 中添加 css 解析的 loader 配置:

  1. // webpack.config.js


  2. module: {

  3. rules: [

  4. {

  5. test: /\.css$/,

  6. use: ["style-loader", "css-loader"]

  7. }

  8. ]

  9. }

参数介绍:

test需要匹配的模块后缀名; use:对应处理的 loader 插件名称(处理顺序是从右往左)。

3. 打包测试

  1. npx webpack


  2. // 输出:


  3. Hash: 28b3965aa1b6a0047536

  4. Version: webpack 4.39.1

  5. Time: 482msBuilt at: 2019-08-0907:45:25AssetSizeChunksChunkNames

  6. main.js 565KiB main [emitted] main

  7. Entrypoint main = main.js

  8. [./node_modules/_css-loader@3.2.0@css-loader/dist/cjs.js!./src/style/index.css] 190 bytes {main} [built]

  9. [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built][./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {main} [built][./src/index.js] 303 bytes {main} [built]

  10. [./src/style/index.css] 447 bytes {main} [built]

  11. + 3 hidden modules

这时候可以看见 index.html 中,文本已经变成红色,并且 css 代码已经添加到 <style> 标签上。

三、 webpack 模块介绍和处理 sass

在这一节中,我们会介绍 webpack 中的模块,并且介绍如何去处理 sass 文件。

1. webpack 模块介绍

这里介绍的模块(module)是指 webpack.config.js 文件中的 module 配置,它决定了如何处理项目中的不同类型模块。

比如上一节介绍的,使用 style-loader 、 css-loader 两个插件去处理 css 文件。

webpack 模块支持如下语句:

  • ES2015 import 语句;

  • CommonJS require() 语句;

  • AMD define 和 require 语句;

  • css/sass/less 文件中 @import 语句;

  • 样式 (url(...)) 或者 HTML 文件 (<img src=...>) 中的图片链接 (image url)

这里建议使用 ES2015 的引入方法,毕竟这是标准。

更多参数介绍,可访问中文官网的介绍:
《webpack 配置选项》 https://www.webpackjs.com/configuration/

2. 常用模块

2.1 module.noParse

值的类型: RegExp|[RegExp]|function

防止 webpack 解析那些符合匹配条件的文件,忽略的文件夹中不应该含有 import、 require、 define的调用,或任何其他导入机制,忽略的 library 可以提高构建效率

  1. // webpack.config.js


  2. module: {

  3. noParse: function(content){

  4. return/jquery|lodash/.test(content);

  5. }

  6. }

2.2 module.rules

创建模块时,匹配请求的规则数组。按照规则为对应模块使用对应的 loader,或修改解析器(parser)。

  1. // webpack.config.js


  2. module: {

  3. rules: [

  4. { test: /\.css$/, use: ['style-loader', 'css-loader']}

  5. ]

  6. }

  • module.rules 参数有:

use:为模块使用指定 loader,并且可以传入一个字符串数组,加载顺序从右往左

  • module.rules 匹配条件有:

{test:Condition}匹配特定条件,非必传,支持一个正则表达式正则表达式数组
{include:Condition}匹配特定条件,非必传,支持一个字符串字符串数组
{exclude:Condition}排除特定条件,非必传,支持一个字符串字符串数组
{and:[Condition]}:必须匹配数组中的所有条件;
{or:[Condition]}:匹配数组中任一条件;
{not:[Condition]}:必须排除这个条件;

更多参数介绍,可访问中文官网的介绍:
《Rule》 https://www.webpackjs.com/configuration/module/#rule

  1. // webpack.config.js


  2. module: {

  3. rules: [

  4. {

  5. test: /\.css$/,

  6. use: ['style-loader', 'css-loader'],

  7. include: [

  8. path.resolve(__dirname, "app/style.css"),

  9. path.resolve(__dirname, "vendor/style.css")

  10. ]

  11. }

  12. ]

  13. }

3. 加载 Sass 文件

需要使用到 sass-loader 的插件,这里先安装:

  1. npm install sass-loader node-sass --save-dev

在 src/style 目录下添加 leo.scss 文件,并添加内容:

  1. // leo.scss


  2. $bg-color: #ee3;

  3. .box{

  4. background-color: $bg-color;

  5. }

然后在 src/index.js 中引入 leo.scss 文件:

  1. // src/index.js

  2. import'./style/leo.scss';

再 npx webpack 重新打包,并打开 dist/index.html 可以看到背景颜色已经添加上去:

4. 添加快捷打包命令

像 npx webpack 这个命令我们需要经常使用,对于这种命令,我们可以把它写成命令,方便每次使用。

我们在 package.json 的 scripts 中添加一个命令为 build,以后打包只要执行 npm run build即可:

  1. "scripts": {

  2. "build": "npx webpack -c webpack.config.js"

  3. },

这里的 -c webpack.config.js 中, -c 后面跟着的是 webpack 配置文件的文件名,默认可以不写。

四、 webpack 开启 SourceMap 和添加 CSS3 前缀

添加 SourceMap 是为了方便打包之后,我们在项目中调试样式,定位到样式在源文件的位置。

1. 开启 SourceMap

在 css-loader 和 sass-loader 都可以通过设置 options 选项启用 sourceMap

  1. // webpack.config.js


  2. rules: [

  3. {

  4. test: /\.(sc|c|sa)ss$/,

  5. use: [

  6. "style-loader",

  7. {

  8. loader:"css-loader",

  9. options:{ sourceMap: true }

  10. },

  11. {

  12. loader:"sass-loader",

  13. options:{ sourceMap: true }

  14. },

  15. ]

  16. }

  17. ]

再重新打包,看下 index.html 的样式,样式已经定位到源文件上了:

这样我们在开发过程中,调试样式就方便很多了。

2. 为样式添加 CSS3 前缀

这里我们用到 PostCSS 这个 loader,它是一个 CSS 预处理工具,可以为 CSS3 的属性添加前缀,样式格式校验( stylelint),提前使用 CSS 新特性,实现 CSS 模块化,防止 CSS 样式冲突。

首先安装 PostCSS

  1. npm install postcss-loader autoprefixer --save-dev

另外还有:


  • postcss-cssnext 可以让我们使用 CSS4的样式,并能配合 autoprefixer 进行浏览器部分兼容的补全,还支持嵌套语法。



  • precss 类似 scss 语法,如果我们只需要使用嵌套,就可以用它替换 scss



  • postcss-import 让我们可以在 @import CSS文件的时 webpack 能监听并编译。


更多参数介绍,可访问中文官网的介绍:
《postcss-loader》 https://www.webpackjs.com/loaders/postcss-loader/

开始添加 postcss-loader 并设置 autoprefixer

  1. // webpack.config.js


  2. rules: [

  3. {

  4. test: /\.(sc|c|sa)ss$/,

  5. use: [

  6. "style-loader",

  7. {

  8. loader:"css-loader",

  9. options:{ sourceMap: true }

  10. },

  11. {

  12. loader:"postcss-loader",

  13. options: {

  14. ident: "postcss",

  15. sourceMap: true,

  16. plugins: loader => [

  17. require('autoprefixer')(),

  18. // 这里可以使用更多配置,如上面提到的 postcss-cssnext 等

  19. // require('postcss-cssnext')()

  20. ]

  21. }

  22. },

  23. {

  24. loader:"sass-loader",

  25. options:{ sourceMap: true }

  26. },

  27. ]

  28. }

  29. ]

还需要在 package.json 中添加判断浏览器版本:

  1. // package.json


  2. {

  3. //...

  4. "browserslist": [

  5. "> 1%", // 全球浏览器使用率大于1%,最新两个版本并且是IE8以上的浏览器,加前缀

  6. "last 2 versions",

  7. "not ie <= 8"

  8. ]

  9. }

为了做测试,我们修改 src/style/leo.scss 中 .box 的样式:

  1. // src/style/leo.scss


  2. .box{

  3. background-color: $bg-color;

  4. display: flex;

  5. }

然后重新打包,可以看见 CSS3 属性的前缀已经添加上去了:

五、 webpack 将 CSS 抽取成单独文件

在之前学习中,CSS 样式代码都是写到 index.html 的 <style> 标签中,这样样式代码多了以后,很不方便。

于是我们需要将这些样式打包成单独的 CSS 文件。

webpack4 开始使用 mini-css-extract-plugin 插件,而在 1-3 版本使用 extract-text-webpack-plugin

注意:抽取样式以后,就不能使用 style-loader 注入到 html 中。

安装插件:

  1. npm install mini-css-extract-plugin --save-dev

引入插件:

  1. // webpack.config.js


  2. constMiniCssExtractPlugin = require('mini-css-extract-plugin');

然后修改 rules,将 style-loader,替换成 MiniCssExtractPlugin.loader ,然后添加 plugins 配置项:

  1. // webpack.config.js


  2. module: {

  3. rules: [

  4. {

  5. test: /\.(sc|c|sa)ss$/,

  6. use: [

  7. MiniCssExtractPlugin.loader,

  8. {

  9. loader:"css-loader",

  10. options:{ sourceMap: true }

  11. },

  12. {

  13. loader:"postcss-loader",

  14. options: {

  15. ident: "postcss",

  16. sourceMap: true,

  17. plugins: loader => [require('autoprefixer')()]

  18. }

  19. },

  20. {

  21. loader:"sass-loader",

  22. options:{ sourceMap: true }

  23. },

  24. ]

  25. }

  26. ]

  27. },

  28. plugins: [

  29. newMiniCssExtractPlugin({

  30. filename: '[name].css', // 最终输出的文件名

  31. chunkFilename: '[id].css'

  32. })

  33. ]

然后重新打包,这时候可以看到我们 dist 目录下就多了个 main.css 文件:

因为现在已经将 CSS 都抽取成单独文件,所以在 dist/index.html 中,我们需要手动引入 main.css 了:

  1. // index.html


  2. <linkrel="stylesheet"href="main.css">

六、 webpack 压缩 CSS 和 JS

为了缩小打包后包的体积,我们经常做优化的时候,将 CSS 和 JS 文件进行压缩,这里需要使用到不同的插件。

1. 压缩 CSS

使用 optimize-css-assets-webpack-plugin 压缩 CSS 的插件。

安装插件:

  1. npm install optimize-css-assets-webpack-plugin --save-dev

使用插件:

  1. // webpack.config.js


  2. // ... 省略

  3. constOptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

  4. module.exports = {

  5. // ... 省略

  6. plugins: [

  7. // ... 省略

  8. newOptimizeCssAssetsPlugin({})

  9. ],

  10. }

重新打包,可以看到 main.css 已经被压缩成一行代码,即压缩成功~

2. 压缩 JS

使用 uglifyjs-webpack-plugin 压缩 JS 的插件。

安装插件:

  1. npm install uglifyjs-webpack-plugin --save-dev

引入插件:

  1. // webpack.config.js


  2. constUglifyJsPlugin = require('uglifyjs-webpack-plugin');

使用插件:

  1. // webpack.config.js

  2. // ... 省略

  3. module.exports = {

  4. // ... 省略

  5. plugins: [

  6. // ... 省略

  7. newOptimizeCssAssetsPlugin({}),

  8. newUglifyJsPlugin({

  9. cache: true, parallel: true, sourceMap: true

  10. })

  11. ],

  12. }

其中 UglifyJsPlugin 的参数:

cache:当 JS 没有发生变化则不压缩;
parallel:是否启用并行压缩;
sourceMap:是否启用 sourceMap;

然后重新打包,查看 main.js,已经被压缩了:

七、webpack 为文件名添加 hash 值

由于我们打包出来的 css、 js 文件是静态文件,就存在缓存问题,因此我们可以给文件名添加 hash 值,防止缓存。

1. 添加 hash 值

直接在 webpack.config.js 中,为需要添加 hash 值的文件名添加 [hash] 就可以:

  1. // webpack.config.js


  2. module.exports = {

  3. // ... 省略其他

  4. output: {

  5. filename: 'main.[hash].js',

  6. path: path.resolve(__dirname, 'dist')

  7. },

  8. plugins: [

  9. newMiniCssExtractPlugin({

  10. filename: '[name].[hash].css',

  11. chunkFilename: '[id].[hash].css'

  12. }),

  13. ],

  14. }

配置完成后,重新打包,就可以看到文件名中包含了 hash 值了:

2. 动态引用打包后的文件

由于我们前面给打包的文件名添加了 hash 值,会导致 index.html 引用文件错误,所以我们需要让它能动态引入打包后的文件。

这里我们使用 HtmlWebpackPlugin 插件,它可以把打包后的 CSS 或者 JS 文件直接引用注入到 HTML 模版中,就不用每次手动修改。

安装插件:

  1. npm install html-webpack-plugin --save-dev

引入插件:

  1. // webpack.config.js


  2. constHtmlWebpackPlugin = require('html-webpack-plugin');

使用插件:

  1. // webpack.config.js


  2. plugins: [

  3. newHtmlWebpackPlugin({

  4. title: "leo study!", // 生成的文件标题

  5. filename: "main.html", // 最终生成的文件名

  6. minify: { // 压缩选项

  7. collapseWhitespace: true, // 移除空格

  8. removeComments: true, // 移除注释

  9. removeAttributeQuotes: true, // 移除双引号

  10. }

  11. })

  12. ],

关于 html-webpack-plugin 更多介绍可以《查看文档》https://github.com/jantimon/html-webpack-plugin/。

接着我们打包以后,可以看见 dist 目录下,多了 main.html 的文件,格式化以后,可以看出,已经动态引入打包后的 CSS 文件和 JS 文件了:

八、 webpack 清理目录插件

在之前,我们每次打包都会生成新的文件,并且在添加 hash 值以后,文件名不会出现重复的情况,导致旧文件的冗余。

为了解决这个问题,我们需要在每次打包之前,将 /dist 目录清空,再进行打包。

这里我们使用 clean-webpack-plugin 插件来实现。

安装插件:

  1. npm install clean-webpack-plugin --save-dev

引入插件:

  1. // webpack.config.js


  2. constCleanWebpackPlugin = require('clean-webpack-plugin');

使用插件:

  1. // webpack.config.js


  2. plugins: [

  3. newCleanWebpackPlugin()

  4. ],

参数 cleanOnceBeforeBuildPatterns 是表示需要清除的文件夹。

这样我们每次打包之前,都会先将 /dist 目录清空一次,再执行打包。

更多参数介绍,可访问中文官网的介绍:
《clean-webpack-plugin》https://github.com/jantimon/clean-webpack-plugin/。

九、 webpack 图片处理和优化

1. 图片处理

在项目中引入图片:

  1. // src/style/leo.scss


  2. .box{

  3. background-color: $bg-color;

  4. display: flex;

  5. background: url('./../assets/logo.jpg')

  6. }

这时候我们如果直接打包,会报错。

我们需要使用 file-loader 插件来处理文件导入的问题。

安装插件:

  1. npm install file-loader --save-dev

使用插件:

  1. // webpack.config.js


  2. module: {

  3. {

  4. test: /\.(png|svg|jpg|jpeg|gif)$/,

  5. use: ["file-loader"]

  6. }]

  7. },

重新打包以后,发现 dist 目录下多了一个如 373e5e0e214390f8aa9e7abb4c7c635c.jpg 名称的文件,这就是我们打包后的图片。

2. 图片优化

更进一步,我们可以对图片进行压缩和优化,这里我们用到 image-webpack-loader 插件来处理。

安装插件:

  1. npm install image-webpack-loader --save-dev

使用插件:

  1. // webpack.config.js


  2. module: {

  3. {

  4. test: /\.(png|svg|jpg|jpeg|gif)$/,

  5. include: [path.resolve(__dirname, 'src/')],

  6. use: ["file-loader",{

  7. loader: "image-webpack-loader",

  8. options: {

  9. mozjpeg: { progressive: true, quality: 65 },

  10. optipng: { enabled: false },

  11. pngquant: { quality: '65-90', speed: 4 },

  12. gifsicle: { interlaced: false },

  13. webp: { quality: 75 }

  14. }

  15. },

  16. ]

  17. }]

  18. },

更多参数介绍,可访问中文官网的介绍:
《image-webpack-loader》https://github.com/tcoopman/

再重新打包,我们可以看到图片打包前后,压缩了很大:

参考资料

  • 《Webpack4 中文网》

  • 《2019最新Webpack4.0教程4.x 成仙之路》


《Webpack4入门手册(上)(共 18 章)》到这里结束。


总结

本文是根据 《2019最新Webpack4.0教程4.x 成仙之路》 学习总结下来的学习之路,适合入门,涉及范围较多,内容比较长,需要能静下心来学习。

内容如果有误,欢迎留言指点,我会及时修改。

本文代码最终托管在我的 github 上,点击查看(https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Webpack/introduction/README.md)。

希望自己的文章会对各位有所帮助,也欢迎各位大佬指点。


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容