Code Monkey home page Code Monkey logo

blog's Introduction

Hi there 👋

  • 👯 I’m looking to collaborate on front-end development
  • 📫 How to reach me: [email protected]

blog's People

Contributors

mario34 avatar

Watchers

 avatar  avatar

blog's Issues

日常踩坑记录(1)

日常踩坑记录

记录日常的踩坑,在找到解决方案后做个记录

Eslint异常报错

背景:在一个老的项目中,使用的是 eslint + @typescript-eslint/parser

问题描述:eslint有时会出现异常的校验,尽管代码符合规范,并且自动修复会使代码完全混成一坨。最后定位到是@typescript-eslint/parser 的问题,升级本本就解决了issues

特此记录

Taro hooks(函数式组件) 访问组件实例

最初的问题是在调用createVideoContext createAudioContext createMapContext等方法时,第二个参数时当前组件的实例。

函数式组件如何访问组件实例issuesuseScope官方文档
const $scope = useScope()
$scope 指向该组件对应的小程序组件实例

日常踩坑记录(2)

尝试vue-next开发项目,对于移除.native修饰符后组件的所有事件将会绑定到组件内部的跟元素

// 组件
<button>
  <slot/>
</button>
<components @click="onClick" />

表现出来的是即使组件内部没有emit暴露任何事件,组件外部也可以直接声明根元素上的原生事件(click,keyup...)

相关PR

从零开始配置webpack react开发环境

首先初始化项目

npm init

1. 安装webpack

要安装最新版本或特定版本,请运行以下命令之一:

npm install --save-dev webpack
npm install --save-dev webpack@<version>

如果你使用 webpack 4+ 版本,你还需要安装 CLI。

npm install --save-dev webpack-cli

2. 新建文件目录

mkdir ./src ./public ./src/components
vim ./src/index.js
vim ./src/components/HelloWord.js
vim ./public/index.html


# 文件目录格式
|-- Webpack
    |-- package-lock.json
    |-- package.json
    |-- webpack.config.js
    |-- public
    |-- src
        |-- index.js

<!-- public/index.js-->
<body>
  <div id="app"></div>
</body>
// src/index.js
import React from "react";
import HelloWorld from "./components/HellowWorld";

class App extends React.Component {
  render() {
    return <HelloWorld />;
  }
}

ReactDOM.render(<App />, document.getElementById("app"));
// src/components/HelloWorld.js

import React from "react";

export default class App extends React.Component {
  render() {
    return <h1>Hello World</h1>;
  }
}

3. 配置加载器

3.1 构建简单的webpack.common.js配置文件

根据上述文件目录结构,新建配置文件 public/webpack.common.js

const path = require("path");
const webpack = require("webpack");

function resolve(dir) {
  return path.join(__dirname, "..", dir);
}

module.exports = {
  entry: "./src/index.js",
  output: {
    path: util.resolve("dist"),
    filename: "[name].js",
    chunkFilename: "[chunkhash].js",
    jsonpFunction: "myWebpackJsonp"
  }
};

packge.json添加

"scripts": {
  "dev": "webpack --config ./build/webpack.common.js"
},

尝试运行npm run dev

ERROR in ./src/index.js 7:11
Module parse failed: Unexpected token (7:11)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| class App extends React.Component {
|   render() {
>     return <HelloWorld />;
|   }
| }

webpack告诉我们需要使用加载器来处理该文件,针对 react 文件,需要使用babel-loader,对于其他的格式文件,需要进行配置。

由于配置中会用到一些工具,所以新建/build/util.js,引入util.js

const path = require("path");

//返回项目根目录下的dir路径
exports.resolve = function(dir) {
  return path.join(__dirname, "..", dir);
};

//返回dits中文件路径下的dir路径
exports.staticPath = function(dir) {
  return path.join("static/", dir);
};

3.2 配置babel-loader

npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react

webpack.config.js添加 babel 配置

...

module: {
  rules: [
    {
      test: /\.js?$/,
      include: [util.resolve('src')],
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env', '@babel/preset-react']
        }
      }
    }
  ]
}
...

3.3 配置.css .scss文件 loader

sass-loader依赖node-sass,由于这个包存放在 github 上,下载速度比较慢,可使用淘宝源下载

npm install sass-loader node-sass css-loader style-loader --save-dev --registry https://registry.npm.taobao.org

webpack.config.jsrules 添加配置

...

  {
    test: /\.css$/,
    use: [{ loader: "style-loader" }, { loader: "css-loader" }]
  },
  {
    test: /\.scss$/,
    use: [
      { loader: "style-loader" }, // 将 JS 字符串生成为 <style> 节点
      { loader: "css-loader" }, // �将 CSS 转化成 CommonJS 模块
      { loader: "sass-loader" } // 将 Sass 编译成 CSS
    ]
  }

...

3.4 配置图片文件的加载

关于图片或文件的相关loader

  • file-loader默认情况下,生成的文件的文件名就是文件内容的 MD5 哈希值并会保留所引用资源的原始扩展名。

  • url-loader 功能类似于 file-loader,但是在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL。⚠️ 注意url-loader依赖 file-loader

这里选择使用url-loader

npm install --save-dev url-loader file-loader

webpack.config.jsrules 添加配置

...

  {
    test: /\.(png|jpg|jpeg|gif)$/,
    use: [
      {
        loader: 'url-loader',
        options: {
          limit: 6000,
          name: util.staticPath('images/[name][hash].[ext]'),
        }
      }
    ]
  }

...

4. 开发环境构建

区分productiondevelopment环境下的配置

vim ./build/webpack.dev.js ./build/webpack.prod.js

4.1 安装相关功能依赖

# 用于合并webpack配置
npm install --save-dev webpack-merge

# 分别用于构建时清除dist目录和拷贝处理index.html
npm install --save-dev clean-webpack-plugin html-webpack-plugin

# 用于启动开发服务器
npm install --save-dev webpack-dev-server

# 用于开发时模块热重载
npm install --save-dev hot-module-replacement-plugin

# 产品模式压缩js
npm install --save-dev uglifyjs-webpack-plugin

# 提取css、压缩css(替代ExtractTextWebpackPlugin)
npm install --save-dev mini-css-extract-plugin

# 注入process.env变量
npm install --save-dev cross-env

⚠️ 需要注意的是:在 css 文件的loader配置中MiniCssExtractPlugin.loaderstyle-loader不能同时使用。

修改webpack.common.js

const devMode = process.env.NODE_ENV !== 'production'
...
//rules
{
  test: /\.css$/,
  use: [
    devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
    "css-loader"
  ]
},
{
  test: /\.scss$/,
  use: [
    devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
    { loader: "css-loader" }, // �将 CSS 转化成 CommonJS 模块
    { loader: "sass-loader" } // 将 Sass 编译成 CSS
  ]
},
...

...
plugins: [
  new HtmlWebpackPlugin({
    template: util.resolve('public/index.html'),
    filename: util.resolve('dist/index.html'),
    favicon: util.resolve('public/favicon.ico')
  }),
],
resolve: {
  extensions: [".js", ".json", ".jsx", ".css"],
  alias: {
    '@': util.resolve('src')//路径别名 可添加 jsconfig.json 配合编辑器提供路径提示功能
  }
},
...

分别添加webpack.prod.js webpack.dev.js文件

webpack.prod.js

const merge = require("webpack-merge");
const UglifyJSPlugin = require("uglifyjs-webpack-plugin");
const common = require("./webpack.common.js");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = merge(common, {
  mode: "production",
  output: {
    path: util.resolve("dist"),
    filename: util.staticPath("js/[name].[chunkhash].js"),
    chunkFilename: util.staticPath("js/[id].[chunkhash].js")
  },
  plugins: [
    new webpack.DefinePlugin({
      'env.PRODUCTION': "true",
    }),
    new UglifyJSPlugin(),
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: util.staticPath("style/[name].css"),
      chunkFilename: util.staticPath("style/[id].css")
    })
  ]
});

webpack.dev.js

const merge = require("webpack-merge");
const common = require("./webpack.common.js");
const webpack = require("webpack);

module.exports = merge(common, {
  mode: "development",
  devServer: {
    contentBase: "./dist"
  },
  pluging: [new webpack.HotModuleReplacementPlugin()],
  devtool: "source-map"
});

4.2 修改scripts

"dev": "cross-env NODE_ENV=development webpack-dev-server --inline --progress  --config ./build/webpack.dev.js"
"build": "cross-env NODE_ENV=production webpack --config ./build/webpack.prod.js"

现在执行npm run dev将会得到一个简单的开发环境

5. 功能的进一步完善

到此为止我们完成了一个简单的配置,在开发环境下实现热重载、加载样式文件,生产环境下代码压缩、自动拷贝index.html并注入script、打包自动清理dist文件夹。下面继续完善相关的功能。

5.1 配置devserver

配置如下,命令行只显示警告或错误信息,同时使用friendly-errors-webpack-plugin插件,自动清除信息,并自定义显示信息内容。

npm install --save-dev friendly-errors-webpack-plugin

webpack.dev.js

const devServerConfig = {
  contentBase: util.resolve("dist"),
  clientLogLevel: "warning",
  port: 3000,
  hot: true,
  host: "localhost",
  open: false,
  quiet: true,
  overlay: {
    /**
     * Shows a full-screen overlay in the browser
     * when there are compiler errors or warnings.
     */
    warnings: false,
    errors: true
  },
  proxy: {
    // detail: https://www.webpackjs.com/configuration/dev-server/#devserver-proxy
    "/base": {
      target: "https://test.cn",
      secure: true,
      changeOrigin: true,
      pathRewrite: {
        "^/base": ""
      }
    }
  }
};

module.exports = merge(common, {
  mode: "development",
  plugins: [
    new webpack.DefinePlugin({
      "env.PRODUCTION": "false"
    }),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new FriendlyErrorsPlugin({
      compilationSuccessInfo: {
        messages: [
          `You application is running here http://${devServerConfig.host}:${devServerConfig.port}`
        ]
      },
      clearConsole: true
    })
  ],
  devServer: devServerConfig,
  devtool: "source-map"
});

5.2配置buils.js文件

安装依赖

npm install --save-dev chalk ora

新建build/build.js,修改scripts.build cross-env NODE_ENV=production node ./build/build.jsora能在命令行显示的加载动画,chalk能够输出带有颜色的文字或消息。

const webpack = require("webpack");
const webpackConfig = require("./webpack.prod");
const ora = require("ora");
const chalk = require("chalk");

const spinner = ora("buildind...");
spinner.start();

webpack(webpackConfig, (err, stats) => {
  spinner.stop();
  if (err) throw err;
  process.stdout.write(
    stats.toString({
      colors: true,
      modules: false,
      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
      chunks: false,
      chunkModules: false
    }) + "\n\n"
  );

  if (stats.hasErrors()) {
    console.log(chalk.red("  Build failed with errors.\n"));
    process.exit(1);
  }

  console.log(chalk.cyan("  Build complete.\n"));
});

5.3 本机地址访问

首先需要获取本机地址,nodejs os 模块提供了相关的功能。

build/util.js

...
const os = require('os')
...

exports.localAddress = function(dir) {
  var network = os.networkInterfaces()
  for (var key in network) {
    for (var i = 0; i < network[key].length; i++) {
      var item = network[key][i]
      if(item.family === 'IPv4'&& item.address !== '127.0.0.1' && !item.internal){
        return item.address
      }
    }
  }
}

修改devServerConfig.host'0.0.0.0',再修改FriendlyErrorsPlugin配置

/build/webpack.dev.js

...
new FriendlyErrorsPlugin({
  compilationSuccessInfo: {
    messages: [`App running at:\n\n - Local:   http://localhost:${devServerConfig.port}/\n - Network: http:/{util.localAddress()}:${devServerConfig.port}`],
  },
  clearConsole: true
})
...

5.4 添加eslint

具有完备的eslint配置可以极大程度上规范编码格式,同时配合编辑器的保存自动根据配置修复,开发体验较好,如果不想使用eslint可以在webpack.dev.js中设置(不推荐)

安装相关插件

npm install --save-dev eslint eslint-friendly-formatter eslint-loader eslint-plugin-react

eslint-loader配合eslint-friendly-formatter能够在编译时将代码与eslintrc冲突的错误显示在命令行

修改webpack.common.js

...
const createLintingRule = () => ({
  test: /\.(js|ts|jsx)$/,
  loader: 'eslint-loader',
  enforce: 'pre',
  include: [util.resolve('src')],
  options: {
    formatter: require('eslint-friendly-formatter'),
    emitWarning: true
  }
})
...
// 可以通过提取一个config配置文来单独开关相关功能而不需要直接修改配置文件
rules:[
  ...(config.eslint ? [createLintingRule()] : []),
  ...
]
...

前端项目的代码风格校验相关配置

在进行项目开发时统一代码规范十分的重要,这里记录的是我的一些相关操作的经验

eslint相关配置

随着tslint社区和eslint社区的推动,目前推荐使用eslint做ts的风格校验(安装对应的插件即可@typescript-eslint/eslint-plugin),所以不管是js项目还是ts项目,都使用eslint就对了。

The TypeScript Team themselves also announced their plans to move the TypeScript codebase from TSLint to typescript-eslint, and they have been big supporters of this project. More details at microsoft/TypeScript#30553

Migrating from TSLint to ESLint If you are looking for help in migrating from TSLint to ESLint, you can check out this project: https://github.com/typescript-eslint/tslint-to-eslint-config

不同文件类型的校验使用不同的插件

建议在eslint配置中加入extends: ["eslint:recommended"]
eslint:recommended规则能够校验出常见的代码风格错误,其他的代码风格规则需要在配置中声明

No rules are enabled by default. The "extends": "eslint:recommended" property in a configuration file enables rules that report common problems, which have a check mark below.

  • react项目

eslint-plugin-react

  • vue项目

eslint-plugin-vue

确保上述配置正确,如果你使用的是VsCode编辑器,安装eslint插件,并设置编辑器保存时进行fix操作,能够极大的提升工作效率。在代码编写阶段就能够解决代码风格问题,不必等到commit时在去处理风格不一致问题。
WebStorm用户同样可以实现上述功能,我不太熟悉WebStorm的配置 : )...

使用 husky+lint-staged+prettier 优化代码格式

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.