快来跟我一起学 React(Day3)

简介

上一节我们介绍了 React 官方提供的脚手架(create-react-app),然后用官方脚手架创建了一个 react-demo1 项目,用脚手架创建出来的项目算是 React 官方认为的最佳项目实践了,但是从上一节使用中我们可以看出,官方脚手架可还是有一些弊端,它只提供一些可改的 webpack 配置,如果你想自己添加一个 loaderplugin 什么的,你可能就需自定义 webpack 配置了,就不能在依赖脚手架了,既然是重新学习 React,我们就来挑战一下自己,从 0 开始搭建一个企业级的 React 项目,大家跟紧节奏吧。

知识点

  • Webpack (打包编译)
  • TypeScript(语法规范)
  • React(js 框架)
  • html-webpack-plugin(webpack 插件)
  • Sass(css 预处理框架)
  • PostCss(css 预处理框架)
  • mini-css-extract-plugin(提取 css 模块插件)
  • Babel( es 语法转化)
  • Jsx & Tsx(jsx 语法)
  • ESLint(代码质量校验)
  • Optimization(项目优化)

ok!要搭建一个企业级的项目需要准备的东西还是有点多的,我们分一下类:

  • Js 框架(Vue、TypeScript、Tsx、Jsx)
  • Css 样式(Sass)
  • 工程化工具(Eslint、Babel、webpack、webpack-chain)

我们开始吧。

项目初始化

我们创建一个 cus-react-demo 目录,然后在 cus-react-demo 目录下执行 npx init -y 命令:

mkdir cus-react-demo && cd cus-react-demo && npm init -y
1

如上图所示,初始化完毕后会看到一个 package.json 文件。

webpack

接下来我们需要安装 webpack 相关的依赖:

安装 webpack

webpack 核心库。

在工程目录 cus-react-demo 执行以下命令安装 webpack:

npm install -D webpack --registry https://registry.npm.taobao.org

目前 webpack 的版本是 5.26.3

安装 webpack-cli

webpack 指令库。

在工程目录 cus-react-demo 执行以下命令:

npm install -D webpack-cli --registry https://registry.npm.taobao.org

安装 webpack-dev-server

webpack 开发者服务框架。

在工程目录 cus-react-demo 执行以下命令:

npm install -D webpack-dev-server --registry https://registry.npm.taobao.org

安装 webpack-chain

webpack 配置工具。

在工程目录 cus-react-demo 执行以下命令:

npm install -D webpack-chain --registry https://registry.npm.taobao.org

创建 webpack 配置

在工程目录 cus-react-demo 下创建一个 webpack.config.js 文件:

touch webpack.config.js

然后对 webpack.config.js 进行配置,用 webpack-chain 导入一个 webpack 配置:

const config = new (require('webpack-chain'))();

module.exports = config.toConfig();

安装 cross-env

定义 node 中的 process.env 中的变量。

在工程目录 cus-react-demo 执行以下命令:

npm install -D cross-env --registry https://registry.npm.taobao.org

为了开发方便,我们在 package.json 中声明两个脚本 builddev

{
  "name": "cus-react-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "rimraf dist && cross-env NODE_ENV=production webpack --mode=production",
    "start": "cross-env NODE_ENV=development webpack serve --mode=development --progress"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "cross-env": "^7.0.3",
    "webpack": "^5.26.3",
    "webpack-chain": "^6.5.1",
    "webpack-cli": "^4.5.0",
    "webpack-dev-server": "^3.11.2"
  }
}

我们可以试着运行一下 buildstart 脚本命令:

npm start
1-2.png

现在运行肯定是报错的,因为我们还没有对项目进行任何配置。

入口与出口

我们首先在工程目录 cus-react-demo 下创建一个 src 目录,然后在 src 目录下创建一个 main.tsx 文件:

mkdir src && cd src && touch main.tsx && cd ..

然后我们找到 webpack.config.js 文件,对 webpack 的入口和出口进行配置:

const path = require('path');
const config = new (require('webpack-chain'))();
const isDev = process.env.NODE_ENV === 'development'; // 判断是否是开发环境
config
    .context(path.resolve(__dirname, '.')) // webpack 上下文目录为项目根目录
    .entry('app') // 入口文件名称为 app
        .add('./src/main.tsx') // 入口文件为 ./src/main.tsx
        .end()
    .output
        .path(path.join(__dirname, './dist')) // webpack 输出的目录为根目录的 dist 目录
        .filename(isDev ? '[name].[hash:8].js' : '[name].[contenthash:8].js') // 打包出来的 bundle 名称为 "[name].[contenthash:8].js"
        .publicPath('/') // publicpath 配置为 "/"
        .end();
module.exports = config.toConfig();

可以看到,我们配置了一个 app 入口 ./src/main.ts,然后给所有的输出文件名称改成了 [name].[hash:8].js

我们再次执行 build 命令:

npm run build
1-3.png

可以看到,这次没有报错了。

但是当我们给 src/main.tsx 添加点内容试试:

let a: string = 'hello';

我们再次运行 npm run build 命令:

1-4.png

可以看到,又报错了,这次是因为 webpack 没法去解析 main.tsx 中的 ts 语法,所以接下来我们就需要配置一下 webpackloader 了,让我们的项目能够支持 jsxtstsx 语法。

Babel & TypeScript

因为我们项目是需要支持 ts 语法的,所以我们需要安装一下 TypeScript 相关依赖:

babel-preset-react-app

很幸运哈,React 官方已经提供了一套 babel 插件集合,它会自动的帮我们添加 babel 相关的配置,让我们能够轻松的使用 jsxtstsx 语法,而且不需要考虑 es 语法的兼容性问题,会根据我们的浏览器配置自动做语法兼容等操作。

在工程目录 cus-react-demo 执行以下命令:

npm install -D babel-preset-react-app --registry https://registry.npm.taobao.org

babel-loader

webpack 加载器。

在工程目录 cus-react-demo 下执行以下命令安装:

npm install -D babel-loader --registry https://registry.npm.taobao.org

ok!安装完 Babel 的一些依赖后,我们开始配置 webpack。

找到 webpack.config.js 文件,然后添加 babel-loader 配置:

const path = require('path');
const config = new (require('webpack-chain'))();
const isDev = process.env.NODE_ENV === 'development'; // 判断是否是开发环境
config
    .context(path.resolve(__dirname, '.')) // webpack 上下文目录为项目根目录
    .entry('app') // 入口文件名称为 app
        .add('./src/main.tsx') // 入口文件为 ./src/main.tsx
        .end()
    .output
        .path(path.join(__dirname, './dist')) // webpack 输出的目录为根目录的 dist 目录
        .filename('[name].[contenthash:8].js') // 打包出来的 bundle 名称为 "[name].[contenthash:8].js"
        .publicPath('/') // publicpath 配置为 "/"
        .end()
    .resolve
        .extensions.add('.js').add('.jsx').add('.ts').add('.tsx').end() // 添加后缀自动解析
        .end()
    .module
        .rule('ts') // 配置 typescript
            .test(/\.(js|mjs|jsx|ts|tsx)$/)
            .exclude
                .add(filepath => {
                    // Don't transpile node_modules
                    return /node_modules/.test(filepath)
                })
                .end()
            .use('babel-loader')
                .loader('babel-loader')
                .end()
            .end()
module.exports = config.toConfig();

然后我们需要在工程目录 cus-react-demo 下创建一个文件 babel.config.js

touch babel.config.js

然后写入以下代码到 babel.config.js 文件:

module.exports = {
    presets: [
        [
            "babel-preset-react-app", // 添加 react-app 插件集合
        ],
    ]
}

TypeScript 配置

因为我们需要进行 ts 语法的我们还需要在工程目录 cus-react-demo 下创建一个 ts 配置文件 tsconfig.json

touch tsconfig.json

然后写入以下代码到 tsconfig.json 文件:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "suppressImplicitAnyIndexErrors": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": ["webpack-env"],
    "paths": {
      "@/*": ["src/*"]
    },
    "lib": ["esnext", "dom", "dom.iterable"]
  },
  "include": ["src/**/*.ts", "src/**/*.tsx",],
  "exclude": ["node_modules"]
}

ok!我们再次运行 npm run build 命令:

1-5.png

可以看到,这一次 webpack 正常完成了编译打包。

React 配置

我们首先安装一下 React 所需要的依赖:

安装 react & react-dom

React 核心 API。

在工程目录 cus-react-demo 执行以下命令:

npm install react react-dom @types/react @types/react-dom --registry https://registry.npm.taobao.org

然后我们修改一下 src/main.tsx 文件来测试一下:

import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
    <div>hello react</div>,
    document.getElementById('root')
);

很简单,就是利用 tsx 语法在页面中输出了一句 “hello react” 字符串。

如果需要开启 webpack-dev-server 的话,我们还需要配置一下 devServer

我们找到 webpack.config.js 配置文件,然后添加 devServer 配置:

const path = require('path');
const config = new (require('webpack-chain'))();
const isDev = process.env.NODE_ENV === 'development'; // 判断是否是开发环境
config
    .context(path.resolve(__dirname, '.')) // webpack 上下文目录为项目根目录
    .entry('app') // 入口文件名称为 app
        .add('./src/main.tsx') // 入口文件为 ./src/main.tsx
        .end()
    .output
        .path(path.join(__dirname, './dist')) // webpack 输出的目录为根目录的 dist 目录
        .filename(isDev ? '[name].[hash:8].js' : '[name].[contenthash:8].js') // 打包出来的 bundle 名称为 "[name].[contenthash:8].js"
        .publicPath('/') // publicpath 配置为 "/"
        .end()
    .resolve
        .extensions.add('.js').add('.jsx').add('.ts').add('.tsx').end() // 添加后缀自动解析
        .end()
    .module
        .rule('ts') // 配置 typescript
            .test(/\.(js|mjs|jsx|ts|tsx)$/)
            .exclude
                .add(filepath => {
                    // Don't transpile node_modules
                    return /node_modules/.test(filepath)
                })
                .end()
            .use('babel-loader')
                .loader('babel-loader')
                .end()
            .end()
    .end()
    .devServer
        .host('0.0.0.0') // 服务器外部可访问
        .disableHostCheck(true) // 关闭白名单校验
        .contentBase(path.resolve(__dirname, './public')) // 设置一个 express 静态目录
        .historyApiFallback({
            disableDotRule: true, // 禁止在链接中使用 "." 符号
            rewrites: [
                { from: /^\/$/, to: '/index.html' }, // 将所有的 404 响应重定向到 index.html 页面
            ],
        })
        .port(8080) // 当前端口号
        .hot(true) // 打开页面热载功能
        .sockPort('location'); // 设置成平台自己的端口
module.exports = config.toConfig();

ok!然后我们在工程目录 cus-react-demo 下执行 npm start 开启 webpack-dev-server

npm start

执行完毕后,我们可以直接用浏览器访问一下打包过后的目录(http://127.0.0.1:8080/webpack-dev-server):

1-6.png

可以看到,webpack-dev-server 列出了 webpack 打包出来的所有 js 资源文件。

接下来我们在工程目录 cus-react-demo 底下创建一个 public 目录,然后在 public 目录下创建一个 index.html 文件作为我们 app 的入口页面:

mkdir public && touch public/index.html

然后写入以下代码到 public/index.html 文件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <noscript>your browser should support javascript!</noscript>
    <!-- 挂载点 -->
    <div id="root"></div>
    <!-- 引入入口文件 -->
    <!-- 注意!这里的 64a558f4 每个人是不一样的 -->
    <script src="/app.64a558f4.js"></script>
  </body>
</html>

注意!这里的 64a558f4 每个人是不一样的)创建完毕后,我们重启服务:

npm start

然后我们可以直接用浏览器访问 http://127.0.0.1:8080/ 项目入口了:

1-7.png

可以看到,页面渲染了我们在 src/index.js 入口文件中定义的 “hello react” 字符串。

html-webpack-plugin

虽然浏览器中正常显示了我们的结果,但是我们现在还是手动去引入 app.xxx.js 文件的,而 xxx 是经常变化的,所以我们不可能每次都去改 public/index.html 文件,能不能自动去引入 js 资源文件到入口 index.html 呢?

安装 html-webpack-plugin

在工程目录 cus-react-demo 执行以下命令:

npm install -D html-webpack-plugin --registry https://registry.npm.taobao.org

然后修改一下 webpack.config.js 配置文件,引入 html-webpack-plugin 插件:

const path = require('path');
const config = new (require('webpack-chain'))();
const isDev = process.env.NODE_ENV === 'development'; // 判断是否是开发环境
config
        .target('web')
    .context(path.resolve(__dirname, '.')) // webpack 上下文目录为项目根目录
    .entry('app') // 入口文件名称为 app
        .add('./src/main.tsx') // 入口文件为 ./src/main.tsx
        .end()
    .output
        .path(path.join(__dirname, './dist')) // webpack 输出的目录为根目录的 dist 目录
        .filename(isDev ? '[name].[hash:8].js' : '[name].[contenthash:8].js') // 打包出来的 bundle 名称为 "[name].[contenthash:8].js"
        .publicPath('/') // publicpath 配置为 "/"
        .end()
    .resolve
        .extensions.add('.js').add('.jsx').add('.ts').add('.tsx').end() // 添加后缀自动解析
        .end()
    .module
        .rule('ts') // 配置 typescript
            .test(/\.(js|mjs|jsx|ts|tsx)$/)
            .exclude
                .add(filepath => {
                    // Don't transpile node_modules
                    return /node_modules/.test(filepath)
                })
                .end()
            .use('babel-loader')
                .loader('babel-loader')
                .end()
            .end()
    .end()
    .plugin('html') // 添加 html-webpack-plugin 插件
        .use(require('html-webpack-plugin'), [
            {
                template: path.resolve(__dirname, './public/index.html'), // 指定模版文件
                chunks: ['app'], // 指定需要加载的 chunk
                inject: 'body', // 指定 script 脚本注入的位置为 body
            },
        ])
        .end()
    .devServer
        .host('0.0.0.0') // 服务器外部可访问
        .disableHostCheck(true) // 关闭白名单校验
        .contentBase(path.resolve(__dirname, './public')) // 设置一个 express 静态目录
        .historyApiFallback({
            disableDotRule: true, // 禁止在链接中使用 "." 符号
            rewrites: [
                { from: /^\/$/, to: '/index.html' }, // 将所有的 404 响应重定向到 index.html 页面
            ],
        })
        .port(8080) // 当前端口号
        .hot(true) // 打开页面热载功能
        .sockPort('location'); // 设置成平台自己的端口
module.exports = config.toConfig();

ok!配置完毕后,我们就可以去掉 public/index.html 中的入口 js 文件了,让其自动引入:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Title</title>
</head>
<body>
<noscript>your browser should support javascript!</noscript>
<!-- 挂载点 -->
<div id="root"></div>
<!-- html-webpack-plugin 将自动引入入口文件 -->
</body>
</html>

我们再次执行 npm start 命令启动项目:

npm start

效果跟之前一致,我就不演示了。

css 样式(Sass)

安装 Sass

Sass & Scss 语法核心 API。

在工程目录 sy_webpack-wedding 执行以下命令:

npm install -D sass --registry https://registry.npm.taobao.org

安装 sass-loader

Sass & Scss 文件加载器。

在工程目录 sy_webpack-wedding 执行以下命令:

npm install -D sass-loader --registry https://registry.npm.taobao.org

安装 postcss-loader

css 样式处理工具,自动添加浏览器适配前缀、压缩 css 样式等等。

在工程目录 sy_webpack-wedding 执行以下命令:

npm install -D postcss-loader --registry https://registry.npm.taobao.org

然后我们在工程目录 sy_webpack-wedding 下创建一个 postcss.config.js 作为 postcss 的配置文件:

touch postcss.config.js

写入以下代码到 postcss.config.js 文件:

module.exports = {
  plugins: [
    require('autoprefixer')(), // 添加 autoprefixer 插件做自动添加样式前缀
    require('cssnano')({
      // 添加 cssnano 插件做 css 代码压缩
      preset: [
        'default',
        {
          mergeLonghand: false,
          cssDeclarationSorter: false,
        },
      ],
    }),
  ],
};

安装 cssnano

压缩 css 代码。

在工程目录 sy_webpack-wedding 执行以下命令:

npm install -D cssnano --registry https://registry.npm.taobao.org

安装 autoprefixer

自动添加浏览器样式适配前缀。

在工程目录 sy_webpack-wedding 执行以下命令:

npm install -D autoprefixer@^9.8.5 --registry https://registry.npm.taobao.org

要让 autoprefixer 插件起作用,我们还需要配置一个项目所支持的浏览器列表文件 .browserslistrc,于是我们在工程目录 sy_webpack-wedding 下创建一个 .browserslistrc 文件:

touch .browserslistrc

然后写入以下内容到 .browserslistrc 文件:

> 0.25%, not dead

意思就是告诉 autoprefixer 插件,我们项目需要兼容的浏览器是 “大于市面上 0.25% 使用率的浏览器,请根据我配置的浏览器列表自动判读是否应该添加 css 前缀做兼容”。

安装 css-loader

css 模块加载器。

在工程目录 sy_webpack-wedding 执行以下命令:

npm install -D css-loader --registry https://registry.npm.taobao.org

安装 mini-css-extract-plugin

抽离 css 样式到独立的 .css 文件。

在工程目录 sy_webpack-wedding 执行以下命令:

npm install -D mini-css-extract-plugin --registry https://registry.npm.taobao.org

ok!安装完 Sass 相关的依赖后,我们来修改一下 webpack.config.js 文件,让 webpack 支持 Sass

const path = require('path');
const config = new (require('webpack-chain'))();
const isDev = process.env.NODE_ENV === 'development'; // 判断是否是开发环境
config
    .target('web')
    .context(path.resolve(__dirname, '.')) // webpack 上下文目录为项目根目录
    .entry('app') // 入口文件名称为 app
        .add('./src/main.tsx') // 入口文件为 ./src/main.tsx
        .end()
    .output
        .path(path.join(__dirname, './dist')) // webpack 输出的目录为根目录的 dist 目录
        .filename(isDev ? '[name].[hash:8].js' : '[name].[contenthash:8].js') // 打包出来的 bundle 名称为 "[name].[contenthash:8].js"
        .publicPath('/') // publicpath 配置为 "/"
        .end()
    .resolve
        .extensions.add('.js').add('.jsx').add('.ts').add('.tsx').end() // 添加后缀自动解析
        .end()
    .module
        .rule('ts') // 配置 typescript
            .test(/\.(js|mjs|jsx|ts|tsx)$/)
            .exclude
                .add(filepath => {
                    // Don't transpile node_modules
                    return /node_modules/.test(filepath)
                })
                .end()
            .use('babel-loader')
                .loader('babel-loader')
                .end()
            .end()
        .rule('sass') // sass-loader 相关配置
            .test(/\.(sass|scss)$/) // Sass 和 Scss 文件
            .use('extract-loader') // 提取 css 样式到单独 css 文件
                .loader(require('mini-css-extract-plugin').loader)
                .end()
            .use('css-loader') // 加载 css 模块
                .loader('css-loader')
                .end()
            .use('postcss-loader') // 处理 css 样式
                .loader('postcss-loader')
                .end()
            .use('sass-loader') // Sass 语法转 css 语法
                .loader('sass-loader')
                .end()
            .end()
        .end()
    .plugin('extract-css') // 提取 css 样式到单独 css 文件
        .use(require('mini-css-extract-plugin'), [
            {
                filename: isDev ? 'css/[name].css': 'css/[name].[contenthash].css',
                chunkFilename: isDev ? 'css/[id].css': 'css/[name].[contenthash].css',
            },
        ])
        .end()
    .plugin('html') // 添加 html-webpack-plugin 插件
        .use(require('html-webpack-plugin'), [
            {
                template: path.resolve(__dirname, './public/index.html'), // 指定模版文件
                chunks: ['app'], // 指定需要加载的 chunk
                inject: 'body', // 指定 script 脚本注入的位置为 body
            },
        ])
        .end()
    .devServer
        .host('0.0.0.0') // 服务器外部可访问
        .disableHostCheck(true) // 关闭白名单校验
        .contentBase(path.resolve(__dirname, './public')) // 设置一个 express 静态目录
        .historyApiFallback({
            disableDotRule: true, // 禁止在链接中使用 "." 符号
            rewrites: [
                { from: /^\/$/, to: '/index.html' }, // 将所有的 404 响应重定向到 index.html 页面
            ],
        })
        .port(8080) // 当前端口号
        .hot(true) // 打开页面热载功能
        .sockPort('location') // 设置成平台自己的端口
        .open(true)
module.exports = config.toConfig();

测试

我们在 src 目录底下创建一个 main.scss 样式文件:

touch ./src/main.scss

然后写入点样式到 src/main.scss 文件:

.root{
  color: red;
  font-size: 30px;
}

接着我们修改一下 src/main.tsx 文件,引入 main.scss 样式:

import React from 'react';
import ReactDOM from 'react-dom';
import "./main.scss";
ReactDOM.render(
    <div className="root">hello react</div>,
    document.getElementById('root')
);

可以看到,我们引入了 main.scss 样式文件,然后给 div 元素上添加了一个 root 类名。

我们重新运行项目看结果:

npm start
1-8.gif

可以看到,当我们修改样式跟内容的时候,页面实时刷新了。

这一节有点长,先到这里了。

总结

我们从 0 开始搭建了一个项目,完成了入口与出口的配置、ts 语法支持、react 基本库的安装、css 样式配置等工作,跟上的小伙伴要给你们点个赞哦,所以整个下来基本上是对 webpack 的配置工作(对 webpack 不熟的小伙伴,强烈推荐去看我前面的文章 《来和 webpack 谈场恋爱吧》:https://www.lanqiao.cn/courses/2893),到这我们只完成了一半的配置工作,我们下节继续。

欢迎志同道合的小伙伴一起交流,一起学习,欢迎私信我~

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