WebStorm工作环境搭建

一、工具准备

WebStorm - 下载

Nodejs - 下载

Chrome - 下载

下载并安装以上工具

二、开发环境搭建

package.json项目打包配置文件

新建package.json文件

可以通过两种方法新建package.json文件:

  1. 使用WebStorm打开对应项目,在项目根目录,右键 - New - package.json File生成一个打包配置文件package.json,应该类似以下结构:

package.json

{
    "name":"项目名称",
    "version":"1.0.0",
    "dependencies":{}
}
  1. 使用WebStorm打开对应项目,通过终端(Terminal)生成package.json
npm init -y

​ 生出的文件应该类似以下结构:

package.json

{
  "name": "项目名称",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}

以上两种方式,建议用第2种方式创建package.json文件。

package.json是打包配置文件,例如程序包需要包含哪些依赖工具,项目的名称、项目版本号、项目描述等。

​ 延伸阅读

package.json详解

typescript工具包

安装typescript

使用WebStorm打开对应项目,通过终端(Terminal)安装typestcript:

npm install typestcript --save-dev

安装typescript,这是后面我们需要安装的tslint所要依赖的工具包。

​ 延伸阅读

--save-dev详解

--save-dev也可以简写成-D,如上面的安装语句也可以写成:

npm install typestcript -D

npm install安装参数详解

新建tsconfig.json文件

可以通过两种方法新建tsconfig.json文件:

  1. 使用WebStorm打开对应项目,在项目根目录,右键 - New - tsconfig.json File生成一个TypeScript配置文件tsconfig.json,应该类似以下结构:

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "sourceMap": true
  },
  "exclude": [
    "node_modules"
  ]
}

  1. 使用WebStorm打开对应项目,通过终端(Terminal)生成tsconfig.json,应该类似以下结构:
tsc --init

​ 如果命令行提示找不到tsc命令的话,有以下两种解决方案:

  1. 命令行进入项目根目录\node_modules\.bin,再次执行命令 tsc --init

    用这种方法,生成的tslint.json文件应该在项目根目录\node_modules\.bin路径下,需要把文件移到项目根目录

  2. 全局安装typescript后,再次执行命令 tsc --init,全局安装typescript的命令为:

npm install typescript -g

​ 用第2种方法生成完毕之后,在项目的根目录应该多了一个文件tslint.json。

tsconfig.json是TypeScript的配置文件。

延伸阅读

tsconfig.json详解

自动编译typescript文件

  1. 进入File - Settings - Languages & Frameworks - TypeScript
  2. 如字段TypeScript出现红色警告或为空,则将其改成项目路径下的typescript工具包的路径,路径位置应该为项目根目录\node_modules\typescript,如配置正确,在该输入框后部会显示typescript的版本号。
  3. 勾选TypeScript Language Service,勾选Recompile on changes,(而其他TypeScript Language Service项目下的复选框根据自己需要自行勾选。)勾选Recompile on changes后,在.ts文件发生变化后,会立即编译成.js文件。
  4. 如果不需要自动编译,可以无需开启自动编译选项。

tslint工具包

安装tslint

使用WebStorm打开对应项目,通过终端(Terminal)安装tslint:

npm install tslint --save-dev

tslint是一个强大的typescript语法检查工具,能帮助我们迅速找到编译错误。

安装完tslint后,package.json文件内应多了"devDependencies"字段的配置,类似以下结构:

package.json

{
    "name":"Your Project Name",
    "version":"1.0.0",
    "dependencies":{},
    "devDependencies":{
        "tslint":"^5.11.0"
    }
}

后续安装新的工具后也会在package.json文件中保存对应的依赖配置。

​ 延伸阅读

tslint官网

开启tslint

安装完后,需要将tslint开启:

1. 进入**File - Settings - Languages & Frameworks - TypeScript - TSLint**;
2. 勾选**Enable**复选框;
3. 如果勾选**Enable**复选框后,字段`TSLint package`出现红色警告,则将其改成项目路径下的tslint package的路径,路径位置应该为`项目根目录\node_modules\tslint`,如配置正确,在该输入框后部会显示tslint的版本号。

生成默认的tslint配置文件

使用WebStorm打开对应项目,通过终端(Terminal)生成tslint默认配置文件:

tslint --init

​ 如果命令行提示找不到tslint命令的话,有以下两种解决方案:

​ 1. 命令行根目录路径进入项目根目录\node_modules\.bin,再次执行命令 tslint --init

​ 用这种方法,生成的tslint.json文件应该在项目根目录\node_modules\.bin路径下,需要把文件移到项目根目录

​ 2. 全局安装tslinttypescript后,再次执行命令 tslint --init,全局安装tslinttypescript的命令为:​

npm install tslint -g
npm install typescript -g

​ 用第2种方法生成完毕之后,在项目的根目录应该多了一个文件tslint.json。

如一切就绪,生成tslint.json后,其内部结构应该类似如下结构:

tslint.json

{
    "defaultSeverity":"error",
    "extends":[
        "tslint:recommended"
    ],
    "jsRules":{},
    "rules":{},
    "rulesDirectory":[]
}

​ 延伸阅读

tslint命令详解

--init也可以简写成-i,如上面的安装语句也可以写成:

tslint -i

prettier工具包

安装prettier

使用WebStorm打开对应项目,通过终端(Terminal)安装prettier:

npm install prettier --save-dev

prettier是一个代码格式美化工具,它可以帮助我们快速按照统一的标准格式格式化工具,在多人协作的项目中可以避免因代码书写习惯不一而导致代码冲突。

​ 延伸阅读

prettier详解

开启prettier文件观察器

安装之后prettier后,每次文件改动(发生变动并保存)后,需要手动输入prettier指令进行文件美化。例如:

prettier --write [文件名 ...]

​ 延伸阅读

prettier cli用法详解

但是我们可以通过WebStorm配置文件观察器来达到自动执行美化,配置方法如下

1. 依次打开 `File - Setting - Tools - File Watchers`;
2. 在右侧窗口右上角处点击`+`按钮,在打开的下来菜单中选择`prettier`,打开`New Watcher`窗口;
3. 在`New Watcher`窗口中,找到 `Files to Watch - File type`配置项,并通过其下拉菜单选择`TypeScript`;
4. 点击`OK`按钮完成配置,之后,只要更改`.ts`文件并保存,将会自动将其编译成`.js`文件。​    

​ 其他配置应该是默认配置好的,无需改动

prettier忽略代码块

某些时候,我们希望代码块不被美化,例如典型的matrix,我们在给matrix赋值的时候为了方便查阅,经常会按以下格式编写:

const matrix = [
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
]

为了不让prettier的规则破坏便于我们阅读的格式,我们可以在代码块前面添加注释// prettier-ignore来达到让prettier忽略该代码块的作用。

// prettier-ignore
const matrix = [
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
]

tslint-config-prettier工具包

安装和配置tslint-config-prettier

使用WebStorm打开对应项目,通过终端(Terminal)安装tslint-config-prettier:

npm install tslint-config-prettier --save-dev

安装完后,打开tslint.json文件,并修改extends字段,使其生效,配置修改如下:

tslint.json

"extends": [
    "tslint:recommended",
    "tslint-config-prettier"
  ]

因为我们最开始安装的tslint和prettier工具有一部分功能重叠,所以会导致功能冲突,而tslint-config-prettier能够解决这些冲突,它将所有代码格式化的责任交给了prettier,而将所有语法检查交给了tslint,使这两个工具各司其职。

​ 延伸阅读

tslint-config-prettier使用详解

webpack工具包

安装webpack

使用WebStorm打开对应项目,通过终端(Terminal)安装webpack(安装耗时比较长,约10分钟):

npm install webpack --save-dev

webpack工具能够帮助我们管理文件模块、给文件增加版本控制、还能通过各种方式提高我们的开发效率。

​ 延伸阅读

webpack工具包文档

安装webpack CLI

使用WebStorm打开对应项目,通过终端(Terminal)安装webpack-cli:

npm install webpack-cli --save-dev

因为我们会使用到webpack的命令行接口,所以除了安装webpack工具本身以外,我们还需要安装webpack-cli,即它的命令行接口。

至此我们已经可以通过npm命令来打包我们的项目了:

npx webpack

此时,打包的起始文件是项目根目录\src\index.js,而打包出来的文件则是项目根目录\dist\main.js,之后,我们需要手动操作将main.js加入程序引用后方可使用,但是我们可以添加一个webpack配置文件来让减少我们的手动操作,请往下看。

新建webpack配置文件

在项目的根目录,新建一个js文件,并命名为webpack.config.js,在文件中加入以下默认基础配置:

webpack.config.js

const path = require('path');

module.exports = {
  entry: '项目的入口js文件名字(相对路径)',
  output: {
    path: path.resolve(__dirname, '输出路径根目录'),
    filename: '打包后的js文件名字(可含路径)'
  }
};

然后我们还需要修改打包配置文件package.json,找到"scripts"字段并新增"build"属性,如下:

package.json

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

添加"build"字段之后,我们就可以通过npm命令来打包,而不是通过npx,请使用以下命令打包:

npm run build

​ 延伸阅读

webpackage多模块导出配置

webpack.config.js配置详解

ts-loader加载器

如果没有开启ts文件自动编译的话,在我们使用webpack打包生成js文件时,需要额外增加ts-loader加载器,以便webpack能够识别和编译ts文件。

安装ts-loader

使用WebStorm打开对应项目,通过终端(Terminal)安装ts-loader:

npm install ts-loader --save-dev

ts-loader配置

安装完毕后,还需要为webpack工具新增配置,在webpacck.config.js中添加module字段和值

webpacck.config.js

module.exports = {
    module:{
        rules: [
            { test: /\.ts$/, use: 'ts-loader' }
        ]
    }
};

modulerules下可以添加多种loader,例如css-loader,这里我们只需要添加ts-loader即可。test属性是检测使用该种loader的正则表达式,而use属性则表示要使用的loader种类

完成以上配置后,我们可以再次通过npm run build来重新导出。

​ 延伸阅读

webpack的loaders使用详解

HtmlWebpackPlugin插件

安装HtmlWebpackPlugin

使用WebStorm打开对应项目,通过终端(Terminal)安装HtmlWebpackPlugin:

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

使用HtmlWebpackPlugin插件的目的是进一步减少我们的人工操作,例如我们有好几个模块需要导出,如:login.js, register.js, main.js,我们通过webpack可将他们分别导出,但是我们还需要手动将他们以<script>标签的形式添加到index.html文件中才能正常使用。

使用HtmlWebpackPlugin插件,可以省去人工添加<script>标签的步骤,下面我们来看看怎么通过修改webpack.config.js来使HtmlWebpackPlugin插件起效。

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');//引用HtmlWebpackPlugin插件

module.exports = {
  entry: '项目的入口js文件名字(相对路径)',
  output: {
    path: path.resolve(__dirname, '输出路径根目录'),
    filename: '打包后的js文件名字(可含路径)'
  },
  //配置HtmlWebpackPlugin插件
  plugins:[
      new HtmlWebpackPlugin({
          title: '主入口HTML文件的<title>标签内的文本',
          filename: '主入口HTML文件的名称,一般为 index.html'
      })
  ]
};

完成以上配置后,我们可以再次通过npm run build来重新导出。

如果一切正常,我们就不需要再通过手动添加<script>标签了,即使我们再新添js模块也不需要手动添加。

但是,这里还有个问题,假如我们修改了某个模块的名称,或者删除了某个模块,那么原来生成的模块js文件依然存在我们的输出路径下,需要手动删除。

​ 延伸阅读

HtmlWebpackPlugin详解

CleanWebpackPlugin插件

使用WebStorm打开对应项目,通过终端(Terminal)安装CleanWebpackPlugin:

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

CleanWebpackPlugin插件能帮助我们清理打包导出路径下的文件,这样每次我们重新导出项目后,将没有多余的模块,这就很好解决了上一小节我们遇到的问题,我们再也不需要手动删除更名后的原模块文件,也不需要手动删除不再使用的模块。下面我们来新增CleanWebpackPlugin的配置来使其生效。

CleanWebpackPlugin配置

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');//引用CleanWebpackPlugin插件

module.exports = {
  entry: '项目的入口js文件名字(相对路径)',
  output: {
    path: path.resolve(__dirname, '输出路径根目录'),
    filename: '打包后的js文件名字(可含路径)'
  },
  
  plugins:[
      new HtmlWebpackPlugin([
          title: '主入口HTML文件的<title>标签内的文本',
          filename:'主入口HTML文件的名称,一般为 index.html'
      ]),
      //配置CleanWebpackPlugin插件
      new CleanWebpackPlugin(['需要清理的路径', ...'其他需要清理的路径'])
  ]
};

配置完成以后可以再次执行npm run build,这时,所配置的清理路径下的文件将先被删除。随后才会生成我们需要的文件,如此,我们不再需要手动删除无用的模块了。

​ 延伸阅读

CleanWebpackPlugin详解

SplitChunksPlugin插件

经过了以上漫长的环境搭建操作,我们已经基本完成了项目打包自动化了,接下来我们还需要考虑的是如何优化我们的打包。虽然我们已经做到了多模块自动化导出,但是假设我们在多模块中同时使用了某个模块,则该被使用的模块将会被重复导入到各个使用它的模块当中,也即是产生了重复的冗余代码。

webpack4.0自带的SplitChunksPlugin插件可以解决这个问题,不需要通过npm来安装新的工具包或插件。下面我们来看看怎么添加SplitChunksPlugin配置。

SplitChunksPlugin配置

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  entry: '项目的入口js文件名字(相对路径)',
  output: {
    path: path.resolve(__dirname, '输出路径根目录'),
    filename: '打包后的js文件名字(可含路径)'
  },
  
  plugins:[
      new HtmlWebpackPlugin([
          title: '主入口HTML文件的<title>标签内的文本',
          filename:'主入口HTML文件的名称,一般为 index.html'
      ]),
      new CleanWebpackPlugin(['需要清理的路径', ...'其他需要清理的路径']),
  ],
  //配置SplitChunksPlugin
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          name: "commons",
          chunks: "initial",
          minChunks: 2,
          minSize:1
        }
      }
    }
  }
};

执行npm run build后,如果有重复使用的模块,那么在输出目录下应该多了一个commons.js文件。

​ 延伸阅读

SplitChunksPlugin配置详解

chunkhash缓存配置

有过前端程序开发的程序员,应该对文件缓存都有所了解。缓存用得好可以大大减少网络加载的负担,但是如果不注意,有可能希望重新加载新资源的时候,却加载的是缓存资源。webpack工具包为我们提供了缓存相关的配置,能满足我们两个需求:

  1. 在导出程序包的时候仅导出发生变化的模块;
  2. 文件发生更新的时候,能保证网络加载时能渠道最新的文件,而不是缓存文件。

基于以上两点,我们有必要为项目添加chunkhash缓存配置,下面我们来看看如何添加:

webpack.config.js

module.exports = {
    output: {
    path: path.resolve(__dirname, '输出路径根目录'),
    filename: '打包后的js文件名字.[chunkhash].js(可含路径)'
  }
}

我们仅仅需要修改output字段的filename属性,即可达到配置目的。在filename的值当中,将[chunkhash]插入到你想加入MD5字符串的位置,例如,filename: 'bundle.[chunkhash].js'

执行npm run build后生成的文件名,应该类似于bundle.7f150679794890f46e2f.js,那么我们的缓存配置就完成了。

CopyWebpackPlugin插件

我们在项目开发过程中,可能会遇到某些文件不需要或不能使用webpack包装的,但是当我们发布项目的时候,这些文件也必须添加到最终的发布文件里面。这种情况下,我们可以引入CopyWebpackPlugin。CopyWebpackPlugin能够帮助我们把必要的文件拷贝到我们的发布路径里,这样就达到了发布的目的了。CopyWebpackPlugin的使用和其他插件也很相像,请看下面的例子。

CopyWebpackPlugin的安装

使用WebStorm打开对应项目,通过终端(Terminal)安装CopyWebpackPlugin:

npm install copy-webpack-plugin --save-dev

CopyWebpackPlugin的使用

CopyWebpackPlugin的使用方法也和其他webpack插件非常类似,在webpack.config.js加入相应的配置即可。

webpack.config.js

const CopyWebpackPlugin =require("copy-webpack-plugin");

module.exports = {
    plugins:[
        new CopyWebpackPlugin([
            {
                from: '需要拷贝的文件名称(可含路径)',
                to:'新的文件名称(可含路径)'
            }
        ])
    ]
}

通过执行npm run build后,相应的文件将被拷贝到对应的位置和名称了。

​ 延伸阅读

CopyWebpackPlugin配置详解

三、运行调试

代码查阅配置

mode字段

我们在开发过程中,难免会遇到程序报错,一旦遇到报错,我们希望能够直达报错所在代码查看报错原因。

当我们将webpack.config.jsmode字段配置为"production"的时候,webpack工具包会将导出的文件进行压缩,所以是打包之后的文件是难以阅读的。

webpack.config.js

module.exports = {
    mode:"production"   //可选值为"none", "development"和"production"
}

那么我们可以将mode字段的值设为"development",这样当我们在浏览器查看报错时,代码的可阅读性得到了大大提高。

webpack.config.js

module.exports = {
    mode:"development"  //可选值为"none", "development"和"production"
}

devtool字段

但毕竟是经过打包的代码,如果我们希望更进一步还原原始代码的话,可以增加devtool字段,如下:

webpack.config.js

module.exports = {
    mode:"development",
    devtool:"inline-source-map"
}

通过执行npm run build后,我们新生成的程序包,如果在运行时报错的话,那么我们可以查看完全还原的代码,迅速找到错误原因。

自动编译

watch命令

这么久以来,每次我们队项目进行改动,或对配置进行改动之后,必须要通过手动执行npm run build才能查看编译后的文件,那么有没有像prettier那样的观察器可以配置呢?

答案是有的,但是配置方式并不像prettier观察器,自动编译无法通过webStorm来配置。相应的,我们来看看该如何让我们的项目自动编译吧。

首先来修改package.json文件

package.json

{
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.config.js",
    "watch": "webpack --watch"
  }
}

我们在打包配置文件package.json中的scripts字段添加了watch属性,实际运行是webpackwatch命令。现在我们在webStorm的终端(Terminal)中执行npm run watch,执行之后终端并没有结束,是因为它正在观察是否有文件发生了修改,一旦发现则会自动编译该文件。

现在只要我们执行过一遍npm run watch之后,就不在需要每次改动文件后去执行npm run build来重新编译文件了。

​ 注意

​ npm run watch命令执行之后,终端是不会自动结束的。如果需要关闭watch进程,只要关闭终端窗口即可。如果还需要执行其他命令,可以开启新的终端窗口。

webpack-dev-server工具包

前面我们已经使用webpack的watch命令来自动编译代码了,那么,如果编译完代码以后,网页还可以自动重新加载这些变动,我们的开发环境就更加智能了。下面我们来看看怎么可以做到热加载。

webpack-dev-server安装

使用WebStorm打开对应项目,通过终端(Terminal)安装webpack-dev-server:

npm install webpack-dev-server --save-dev

安装完后,让我们来看看如何添加相应的配置

webpack.config.js

module.exports = {
    devServer:{
        contentBase:"网站服务器的根目录,也即是我们的打包输出路径"
    }
}

webpack.config.js配置文件中我们添加了devServer的字段,并为其添加contentBase的属性。然后我们需要到package.json配置文件中添加启动网站服务器的脚本配置。

package.json

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

最后,让我们执行npm run server命令来启动网站服务器吧。启动服务器后,会使用默认浏览器打开地址http://localhost:8080。现在我们修改文件后,文件会自动编译打包,而且网页也会自动更新了。

​ 注意

​ 与上面npm run watch提到的问题一样,执行完npm run server后终端是不会自动结束的。如果需要关闭server进程,只要关闭终端窗口即可。如果还需要执行其他命令,可以开启新的终端窗口。

​ 延伸阅读

webpack-dev-server详解


@Freeman

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

推荐阅读更多精彩内容