ppyuex

ppyuex 查看完整档案

苏州编辑重庆社会大学  |  化学 编辑  |  填写所在公司/组织 blog.leanote.com/ethan_you 编辑
编辑

console.log("Hello World")

个人动态

ppyuex 评论了文章 · 2019-02-14

docker 搭建前端开发环境不完全指南

本文需要对docker 和现代前端开发模式有一定了解, docker入门可以参考 docker入门教程
不同系统请自行安装docker环境

初始化项目

目前网上找到的docker 搭建前端开发环境的资料都比较老了, 所以有了此篇文章

docker --version
Docker version 17.09.1-ce, build 19e2cf6

创建项目:

create-react-app my-project-react

安装依赖的过程可以直接ctrl-c停止, 因为我们可以在docker环境中安装依赖

在docker 中安装依赖

拉取docker image, 直接采用node镜像

docker pull node:8.11.4-stretch

下载完成后docker image ls可以查看已经在本地image:

cd my-project-react
docker run  -v `pwd`:/workspace -w /workspace --privileged=true node:8.11.4-stretch yarn

命令具体下文解释
install速度慢的, 可以添加.npmrc 和 .yarnrc文件

registry "https://registry.npm.taobao.org"
sass_binary_site "https://npm.taobao.org/mirrors/node-sass/"
phantomjs_cdnurl "http://cnpmjs.org/downloads"
electron_mirror "https://npm.taobao.org/mirrors/electron/"
sqlite3_binary_host_mirror "https://foxgis.oss-cn-shanghai.aliyuncs.com/"
profiler_binary_host_mirror "https://npm.taobao.org/mirrors/node-inspector/"
chromedriver_cdnurl "https://cdn.npm.taobao.org/dist/chromedriver"

在docker中运行

cd my-project-react

docker run -it -v `pwd`:/workspace -w /workspace -p 8000:8000 --privileged=true node:8.11.4-stretch yarn start

命令比较长, 逐段解释
docker run -it node:8.11.4-stretch
以node:8.11.4-stretch这个image 运行 docker container, -it 表示进入交互式终端;

-v `pwd`:/workspace
稍微熟悉shell脚本的就知道, pwd代表当前目录,pwd反引号代表执行pwd命令, 并输出, 作用就是将当期项目目录挂载到docker 容器中的 /workspace 目录;

-w /workspace --privileged=true
-w 指定工作目录为 /workspace(容器中), --privileged=true, 以防万一, 获取容器的root权限;

-p 8000:8000
将运行中容器的8000端口(项目运行端口)映射到主机的8000端口, 注意, 这两个端口必须一致, 否则热更新有问题.本地localhost:8000无法打开网页, 请先吧webpack-dev-server中host配置改为0.0.0, 再查看本机8000端口占用情况;

yarn start
以开发模式运行项目, 命令根据自己项目实际情况而定.

当然运行run命令也可以不加上 -it 参数, 直接运行, 这样的缺点是无法直接ctrl-c停止运行, 停止container 需要使用 docker container stop containerId命令

在docker中build

以上步骤都ok, build 过程就很简单了, 只需要把 yarn start 命令改成yarn build 即可, 也不需要端口.

docker run -v `pwd`:/workspace -w /workspace  --privileged=true node:8.11.4-stretch yarn build
查看原文

ppyuex 发布了文章 · 2019-01-20

create-react-app 2.0中使用antd(eject)

早些时候CRA(create-react-app)升级到2.0.3的时候, react-app-rewired没有跟着升级, 导致项目无法启动, 于是乎直接eject 开始改造项目.

查看版本

> create-react-app --version
2.0.3

创建项目

create-react-app my-project
cd my-project
yarn eject # 输入 y

目前为止项目目录结构, 忽略node_modules这个黑洞

├── README.md
├── config
│   ├── env.js
│   ├── jest
│   │   ├── cssTransform.js
│   │   └── fileTransform.js
│   ├── paths.js
│   ├── webpack.config.js
│   └── webpackDevServer.config.js
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── scripts
│   ├── build.js
│   ├── start.js
│   └── test.js
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── serviceWorker.js
└── yarn.lock

安装依赖

yarn add antd
yarn add babel-plugin-import less less-loader @babel/plugin-proposal-decorators -D

CRA eject之后package.json里面没有区分devDependencies 和 dependencies, 但是不影响使用

因为antd是使用的less, CRA默认不支持, 所以需要改下默认的webpack配置, config/webpack.config.js

首先修改babel配置

个人习惯使用babelrc, 所以把babel-loader options中babelrc的值改为true, 增加.babelrc文件

{
  "presets": [
    "react-app"
  ],
  "plugins": [
    [
      "import",
      {
        "libraryName": "antd",
        "libraryDirectory": "lib",
        "style": true
      },
      "ant"
    ],
    [
      "@babel/plugin-proposal-decorators", // 启用装饰器
      {
        "legacy": true
      }
    ]
  ]
}

参照默认的sass配置, 增加less配置

const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;

const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;

在module>rules中添加规则

// sass rule
//...
            {
              test: lessRegex,
              exclude: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap
                },
                'less-loader',
                {
                  javascriptEnabled: true
                }
              ),
              sideEffects: true
            },
            {
              test: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                  modules: true,
                  getLocalIdent: getCSSModuleLocalIdent
                },
                'less-loader',
                {
                  javascriptEnabled: true
                }
              )
            }
// file loader

至此基本项目虽然已经基本完成, 但是如果你是使用less版本比较高, 项目是无法运行的
参考issue
需要改造getStyleLoaders函数, 增加第三个参数otherConfig, 就是上面代码中的 javascriptEnabled: true

const getStyleLoaders = (cssOptions, preProcessor, otherConfig) => {
    const loaders = [
      isEnvDevelopment && require.resolve('style-loader'),
      isEnvProduction && {
        loader: MiniCssExtractPlugin.loader,
        options: Object.assign({}, shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined)
      },
      {
        loader: require.resolve('css-loader'),
        options: cssOptions
      },
      {
        loader: require.resolve('postcss-loader'),
        options: {
          ident: 'postcss',
          plugins: () => [
            require('postcss-flexbugs-fixes'),
            require('postcss-preset-env')({
              autoprefixer: {
                flexbox: 'no-2009'
              },
              stage: 3
            })
          ],
          sourceMap: isEnvProduction && shouldUseSourceMap
        }
      }
    ].filter(Boolean);
    if (preProcessor) {
      loaders.push({
        loader: require.resolve(preProcessor),
        options: {
          sourceMap: isEnvProduction && shouldUseSourceMap,
          ...otherConfig
        }
      });
    }
    return loaders;
  };

这样修改之后, 自定义主题modifyVars也可以写在otherConfig中, 一举两得, 不多赘述.

至此项目👌

优化完善, 启用dll

关于dll的利弊不再赘述, 这里只是说明我用的方法, 也不详细展开, 每个人的项目可能都不一样

安装插件

yarn add clean-webpack-plugin webpack-cli add-asset-html-webpack-plugin -D

在config/paths.js exports对象中增加一行kv

 appDll: resolveApp("dll"),

增加config/webpack.dll.conf.js文件

const paths = require('./paths');
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const vendors = [
  'react',
  'react-dom'
];

module.exports = {
  mode: 'production',
  performance: {
    hints: false
  },
  output: {
    path: paths.appDll,
    publicPath: paths.servedPath,
    filename: '[name].[hash].dll.js',
    library: '[name]_[hash]'
  },
  entry: {
    vendor: vendors
  },
  plugins: [
    new CleanWebpackPlugin([paths.appDll], {
      root: paths.appPath, // 根目录
      verbose: true, // 开启在控制台输出信息
      dry: false // 启用删除文件
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),

    new webpack.DllPlugin({
      path: path.join(paths.appDll, '[name]-manifest.json'),
      name: '[name]_[hash]'
    })
  ]
};

package.json增加dll 脚本

 "dll": "webpack --progress --config config/webpack.dll.conf.js"

运行 yarn dll打包vendor在dll文件夹中

生产模式使用dll, 修改webpack.conf.js, 增加assets插件和dllreference插件

...
const AddAssetHtmlPlugin = require("add-asset-html-webpack-plugin");
....

plugins: {
    ...
    ...
    isEnvProduction &&
        new webpack.DllReferencePlugin({
          manifest: require('../dll/vendor-manifest.json')
        }),

      isEnvProduction &&
        new AddAssetHtmlPlugin({
          filepath: path.resolve(paths.appDll, '*.js'),
          includeSourcemap: false
        }),

}

至此结束, 验证效果

yarn build

build 文件夹结构

├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.8175e98134227f2327b88338d3024239.js
├── service-worker.js
├── static
│   ├── css
│   │   ├── 1.83e366fa.chunk.css
│   │   ├── 1.83e366fa.chunk.css.map
│   │   ├── main.c7ff46e9.chunk.css
│   │   └── main.c7ff46e9.chunk.css.map
│   ├── js
│   │   ├── 1.860809fa.chunk.js
│   │   ├── 1.860809fa.chunk.js.map
│   │   ├── main.0df678d7.chunk.js
│   │   ├── main.0df678d7.chunk.js.map
│   │   ├── runtime~main.229c360f.js
│   │   └── runtime~main.229c360f.js.map
│   └── media
│       └── logo.5d5d9eef.svg
└── vendor.52ec4f1c0bead1c1a489.dll.js

本地运行serve -s build, 项目能正常显示, build文件夹下有vendor.hash.dll.js则说明配置成.

查看原文

赞 5 收藏 3 评论 2

ppyuex 关注了用户 · 2018-12-13

染陌同学 @ranmo

公众号:前端技术优选

关注 86

ppyuex 关注了用户 · 2018-11-02

颜海镜 @yanhaijing

知名技术博主,开源达人,《React状态管理与同构实战》作者,http://yanhaijing.com

关注 891

ppyuex 发布了文章 · 2018-10-22

create-react-app 2.0版本如何启用装饰器语法

create-react-app(简称cra)已经更新之2.0.3版本, babel也更新至7.x版本, JavaScript装饰器语法虽然还不是标准, 但是借助于babel, 也能在项目里愉快的玩耍.

cra2.0时代如何启用装饰器语法呢? 我们依旧采用的是react-app-rewired, 通过劫持webpack cofig对象, 达到修改的目的.

yarn add react-app-rewired

修改package.json

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test"
  }

安装装饰器语法所需的babel插件, 也可以顺带升级babel-core

yarn add @babel/plugin-proposal-decorators metro-react-native-babel-preset -D

在项目根目录下创建.babelrc, config-overrides.js文件

// .babelrc
{
  "presets": ["module:metro-react-native-babel-preset"],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ]
  ]
}

// config-overrides
const { getBabelLoader } = require('react-app-rewired');

const path = require('path');

module.exports = function override(config, env) {
  const babelLoader = getBabelLoader(config.module.rules);
  const pwd = path.resolve();
  babelLoader.include = [path.normalize(`${pwd}/src`)];
  // use babelrc
  babelLoader.options.babelrc = true;
  
  return config;
};

原理就是劫持了config对象, 对其babel规则进行简单的修改.
附上完整的package.json

{
  "name": "my-react-project",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.5.2",
    "react-app-rewired": "^1.6.2",
    "react-dom": "^16.5.2",
    "react-scripts": "2.0.5"
  },
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ],
  "devDependencies": {
    "@babel/plugin-proposal-decorators": "^7.1.2",
    "metro-react-native-babel-preset": "^0.48.1",
    "webpack-bundle-analyzer": "^3.0.3"
  }
}
查看原文

赞 1 收藏 0 评论 0

ppyuex 关注了专栏 · 2018-09-30

颜海镜

专注Web前端

关注 717

ppyuex 回答了问题 · 2018-09-11

vue 动态加载路由 页面空白,刷新一下后才能正常显示页面。

没有菜单栏, 路由是有了, 菜单menu值渲染一次, addRoutes后菜单不会变

关注 4 回答 3

ppyuex 发布了文章 · 2018-09-04

docker 搭建前端开发环境不完全指南

本文需要对docker 和现代前端开发模式有一定了解, docker入门可以参考 docker入门教程
不同系统请自行安装docker环境

初始化项目

目前网上找到的docker 搭建前端开发环境的资料都比较老了, 所以有了此篇文章

docker --version
Docker version 17.09.1-ce, build 19e2cf6

创建项目:

create-react-app my-project-react

安装依赖的过程可以直接ctrl-c停止, 因为我们可以在docker环境中安装依赖

在docker 中安装依赖

拉取docker image, 直接采用node镜像

docker pull node:8.11.4-stretch

下载完成后docker image ls可以查看已经在本地image:

cd my-project-react
docker run  -v `pwd`:/workspace -w /workspace --privileged=true node:8.11.4-stretch yarn

命令具体下文解释
install速度慢的, 可以添加.npmrc 和 .yarnrc文件

registry "https://registry.npm.taobao.org"
sass_binary_site "https://npm.taobao.org/mirrors/node-sass/"
phantomjs_cdnurl "http://cnpmjs.org/downloads"
electron_mirror "https://npm.taobao.org/mirrors/electron/"
sqlite3_binary_host_mirror "https://foxgis.oss-cn-shanghai.aliyuncs.com/"
profiler_binary_host_mirror "https://npm.taobao.org/mirrors/node-inspector/"
chromedriver_cdnurl "https://cdn.npm.taobao.org/dist/chromedriver"

在docker中运行

cd my-project-react

docker run -it -v `pwd`:/workspace -w /workspace -p 8000:8000 --privileged=true node:8.11.4-stretch yarn start

命令比较长, 逐段解释
docker run -it node:8.11.4-stretch
以node:8.11.4-stretch这个image 运行 docker container, -it 表示进入交互式终端;

-v `pwd`:/workspace
稍微熟悉shell脚本的就知道, pwd代表当前目录,pwd反引号代表执行pwd命令, 并输出, 作用就是将当期项目目录挂载到docker 容器中的 /workspace 目录;

-w /workspace --privileged=true
-w 指定工作目录为 /workspace(容器中), --privileged=true, 以防万一, 获取容器的root权限;

-p 8000:8000
将运行中容器的8000端口(项目运行端口)映射到主机的8000端口, 注意, 这两个端口必须一致, 否则热更新有问题.本地localhost:8000无法打开网页, 请先吧webpack-dev-server中host配置改为0.0.0, 再查看本机8000端口占用情况;

yarn start
以开发模式运行项目, 命令根据自己项目实际情况而定.

当然运行run命令也可以不加上 -it 参数, 直接运行, 这样的缺点是无法直接ctrl-c停止运行, 停止container 需要使用 docker container stop containerId命令

在docker中build

以上步骤都ok, build 过程就很简单了, 只需要把 yarn start 命令改成yarn build 即可, 也不需要端口.

docker run -v `pwd`:/workspace -w /workspace  --privileged=true node:8.11.4-stretch yarn build
查看原文

赞 3 收藏 3 评论 2

ppyuex 回答了问题 · 2018-06-11

解决请问下vue在微信中分享好友,微信自己加了一些参数,导致链接被破坏,怎么解决?

这个问题很诡异, 我们这边各种试下来, ios上分享正常, 安卓上就会这样路由被吃掉了.
解决方法很简单: 安卓上, 首次打开页面的网址必须带#号
首次进入的网址, http://192.168.1.151:8081/, 分享则有上述情况,
如果首次进入的网址, http://192.168.1.151:8081/#/, 分享则正常

关注 4 回答 3

ppyuex 发布了文章 · 2018-04-22

vue项目升级webpack4指南

所用vue-cli版本为2.9.3, 非最新的3.0+版本, 包管理工具为yarn

现在vue cli 3.x版本已经稳定, 推荐使用 @vue/cli 3.x版本

初始化项目

vue init webpack my-project
cd my-project
yarn install

脚手架项目webpack版本为3.6.0

升级webpack等devdependencies

yarn upgrade webpack@4.6.0
yarn add webpack-dev-server webpack-cli -D

光升级这写是不够的, 此时运行项目会报一些奇奇怪怪的错误, 比如
TypeError: compilation.mainTemplate.applyPluginsWaterfall is not a function
查看错误信息上下文,

/workspace/my-project/node_modules/html-webpack-plugin/lib/compiler.js:81
        var outputName = compilation.mainTemplate.applyPluginsWaterfall('asset-path', outputOptions.filename, {
TypeError: compilation.mainTemplate.applyPluginsWaterfall is not a function

应该是相关插件版本不对, 比如这个错误就是html-webpack-plugin未升级版本导致

继续升级相关plugin

需要升级的相关plugin如下:

html-webpakc-plugin
vue-loader

其他未涉及的, 也尽可能升级到新的版本.

修改webpack等相关配置文件

指定webpack.dev.conf.j和webpack.prod.conf.js 的mode 为developmentproduction, 否则会有警告信息⚠️
The 'mode' option has not been set, webpack will fallback to 'production' for this value.

此时项目已经能在dev-server下顺利运行.
删除多余配置项: webpack.DefinePlugin已不再需要, 在开发模式下, process.env.NODE_ENV 自动被设置为'development', 生成模式下则是production
其他环境变量推荐使用cross-env在命令里设置, 如果需要也可以保留.

cross-env cross-env NODE_ENV=test yarn test

其他插件修改:
NoEmitOnErrorsPlugin 废弃,使用optimization.noEmitOnErrors替代,在生产环境中默认开启
ModuleConcatenationPlugin 废弃,使用optimization.concatenateModules替代,在生产环境默认开启该插件。
NamedModulesPlugin 废弃,使用optimization.namedModules替代,在生产环境默认开启。
uglifyjs-webpack-plugin升级到了v1.0版本, 默认开启缓存和并行功能。
CommonsChunkPlugin 被删除

在配置文件中删除废弃的插件, 至此, 开发模式改造完毕

生产模式改造

应为CommonsChunkPlugin被删除, 改为内置的api, 首先删除webpack.prod.conf.js相关配置(CommonsChunkPlugin和UglifyJsPlugin), 新增项optimization,

 optimization: {
    runtimeChunk: {
      name: 'manifest'
    },
    minimizer: [
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        sourceMap: config.build.productionSourceMap,
        uglifyOptions: {
          warnings: false
        }
      }),
      new OptimizeCSSPlugin({
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { safe: true }
    }),
    ],
    splitChunks:{
      chunks: 'async',
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      name: false,
      cacheGroups: {
        vendor: {
          name: 'vendor',
          chunks: 'initial',
          priority: -10,
          reuseExistingChunk: false,
          test: /node_modules\/(.*)\.js/
        },
        styles: {
          name: 'styles',
          test: /\.(scss|css)$/,
          chunks: 'all',
          minChunks: 1,
          reuseExistingChunk: true,
          enforce: true
        }
      }
    }
  }

extract-text-webpack-plugin已不再被推荐使用, webpack4 推荐使用新的插件mini-css-extract-plugin

yarn add mini-css-extract-plugin  -D

修改配置文件

// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

...
plugins: [
    ...
    // new ExtractTextPlugin({
    //   filename: utils.assetsPath('css/[name].[contenthash].css'),
    //   allChunks: true,
    // }),
    new MiniCssExtractPlugin({
      filename: 'css/app.[name].css',
      chunkFilename: 'css/app.[contenthash:12].css'  // use contenthash *
    }),
]

再修改build/utils文件中extract css的设置

// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
...
    if (options.extract) {
      // return ExtractTextPlugin.extract({
      //   use: loaders,
      //   fallback: 'vue-style-loader'
      // })
      // MiniCssExtractPlugin.loader,
      return [MiniCssExtractPlugin.loader].concat(loaders)
    } else {
      return ['vue-style-loader'].concat(loaders)
    }

yarn build已经能够正常打包, 经过测试, 打包5万行代码的一个项目, webpack4比3快20s左右

经过修改的demo项目github地址
补充: 如果打包的时候出现

WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.

在webpack中增加配置即可

performance: {
  hints: false
}

tips

新版的webpack devserver 如果不指定host, 只能通过localhost访问, 通过ip不能访问, 修改方法很简单, 指明host为 '0.0.0.0'就可以

...
 host: '0.0.0.0', // can be overwritten by process.env.HOST
 port: 8080
...

问题

如果build或者dev时候出现, html-webpack-plugin报错的情况, 请升级该插件, 相关issue

yarn add html-webpack-plugin@next -D

如果报chunksSortMode相关的错误, 请删除chunksSortMode: 'dependency'之后再尝试build

还是建议升级html-webpack-plugin@next

查看原文

赞 18 收藏 16 评论 4

认证与成就

  • 获得 69 次点赞
  • 获得 16 枚徽章 获得 0 枚金徽章, 获得 3 枚银徽章, 获得 13 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2017-03-05
个人主页被 577 人浏览