前端工程不瞭解?帶你踩坑加爬坑。

本文但願能幫助那些一直用腳手架而對工程化沒有概念的朋友。javascript

文中許多步驟會在運行時報錯,從錯誤中分析須要添加的配置,加深印象以及對所添加的每一行配置的理解。css

本文將以React爲例,帶你走一次。html

建立目錄

mkdir demo && cd demo
npm init
touch index.js
複製代碼

webpack

安裝webpack依賴

yarn add webpack webpack-cli --dev # 安裝webpack相關依賴
touch webpack.config.js # 新建webapck配置文件
複製代碼

修改配置

這是一份最基本的webpack配置:前端

const path = require('path');

module.exports = {
  entry: "./index.js",
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};
複製代碼

調整package.json

在package.json中,添加scipts以下:java

"scripts": {
	"build": "webpack"
},
複製代碼

初試build

在命令行中執行node

npm run build
複製代碼

你會看到以下警告:react

WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: webpack.js.org/concepts/mo…webpack

因爲webpack在4.0後,新增mode配置項,它爲咱們默認設置了production。可是該警告並無影響build的結果暫且忽略。 能夠看到dist目錄已經生成了名爲my-first-webpack.bundle.js文件。git

OK,最基本的配置已經完成,接下來引入React。程序員

React

安裝react依賴

yarn add react react-dom # 安裝react相關依賴
複製代碼

使用

在使用前,須要在dist目錄中,添加index.html,內容以下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>React</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="./my-first-webpack.bundle.js"></script>
  </body>
</html>

複製代碼

react官網官網找段HelloWorld貼過來吧,全英文看不懂?不要緊,代碼你總認識吧,貼就完了!

index.js中的內容變動以下:

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);
複製代碼

OK,看似完美,執行下,build看看效果。

ERROR in ./index.js 4:16
Module parse failed: Unexpected token (4:16)
You may need an appropriate loader to handle this file type.
| import ReactDOM from 'react-dom';
|
> ReactDOM.render(<div>Hello World</div>,
|   document.getElementById('root'));
複製代碼

報錯了?莫慌,從錯誤信息中找關鍵字,You may need an appropriate loader to handle this file type.。 這時候感慨一句,程序員是偉大的,錯誤信息很詳細了,告訴咱們須要適當的loader來處理這個文件。什麼loader?別問我,不是我乾的,繼續往下看剛纔的連接下一小節react-jsx的介紹,拉到最下面,是否是有一段關於官方的建議?繼續查找關鍵字,是否是看到一個叫Babel的東西?納尼,莫非jsx和它有關係?雖然這段話是說推薦編輯器設置的吧,可是程序員必備一顆好奇的心。

Babel

Google一下上面的關鍵詞Babel進去瞅瞅吧。 因而開始接觸一個新名詞Babel,這玩意幹啥的?能爲咱們帶來什麼?看看首頁吧。

  • ES2015 及更高版本

    Babel 經過語法轉換器支持最新版本的 JavaScript 。

  • Polyfill

    因爲 Babel 只轉換語法(如箭頭函數), 你可使用 babel-polyfill 支持新的全局變量,例如 Promise 、新的原生方法。

  • JSX 和 Flow

    Babel 可以轉換 JSX 語法並去除類型註釋。

  • 可插拔

    Babel 是創建在插件以外的。 你可使用已有的插件或者本身編寫插件來組成屬於你本身的轉換管道。

  • 可調式

    支持 Source map 所以能夠輕鬆調試編譯後代碼。

看完首頁的介紹,是否和我有一樣的感嘆:好東西啊!既然是好東西,用起來吧。 從配置webpack選項中,你會發現剛纔出現的兩個關鍵字都來了babelloader,艾瑪,得來全不費工夫。

yarn add babel-loader babel-core babel-preset-env babel-polyfill babel-preset-react --dev 
# 這波安裝比較長?由於咱們把剛纔看到的es201五、更高版本語法的,polyfill,jsx的都裝上了
複製代碼

經過config配置

webpack.config.js修改配置以下:

const path = require('path');

module.exports = {
  entry: "./index.js",
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
    ]
  }
};
複製代碼

建立.babelrc配置文件

touch .babelrc #建立.babelrc
複製代碼

將如下內容粘貼至.babelrc中:

{
  "presets": ["env", "react"]
}
複製代碼

至此,已經將上面的babel-preset-envbabel-preset-react使用上了,那polyfill怎麼用呢?繼續看波文檔吧。emmm,寫的很清楚了,咱們把polyfill使用上吧,修改webpack.config.js中的配置以下:

const path = require('path');

module.exports = {
  entry: ["babel-polyfill", "./index.js"],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
    ]
  }
};
複製代碼

該配置的都配置完了,執行下npm run build看看效果?果不其然,編譯過了。

你覺得工程就這樣配完了嗎?NO,這僅僅是個開始!

react-router

SPA工程中使用,什麼是SPA,單頁應用?什麼是單頁應用?只有一個html,公用js css僅引用一次,經過局部刷新渲染的應用。

react-router官網,按着快速上手的步驟來。

安裝

yarn add react-router-dom
複製代碼

使用

Now you can copy/paste any of the examples into src/App.js. Here’s the basic one:

這裏從create-react-app中使用方式,雖然咱們不是,可是咱們本身搭的也不差啊。本身建個srcApp.js吧。

mkdir src && touch src/App.js
複製代碼

將官方的🌰貼進來App.js

import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

const Home = () => (
  <div> <h2>Home</h2> </div>
)

const About = () => (
  <div> <h2>About</h2> </div>
)

const Topic = ({ match }) => (
  <div> <h3>{match.params.topicId}</h3> </div>
)

const Topics = ({ match }) => (
  <div>
    <h2>Topics</h2>
    <ul>
      <li>
        <Link to={`${match.url}/rendering`}>
          Rendering with React
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/components`}>
          Components
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/props-v-state`}>
          Props v. State
        </Link>
      </li>
    </ul>

    <Route path={`${match.path}/:topicId`} component={Topic}/>
    <Route exact path={match.path} render={() => (
      <h3>Please select a topic.</h3>
    )}/>
  </div>
)

const BasicExample = () => (
  <Router>
    <div>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/topics">Topics</Link></li>
      </ul>

      <hr/>

      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
      <Route path="/topics" component={Topics}/>
    </div>
  </Router>
)
export default BasicExample
複製代碼

接下來在index.js中引用:

import React from 'react'
import ReactDOM from 'react-dom';
import App from './src/App';

ReactDOM.render(
  <App />, document.getElementById('root') ); 複製代碼

執行npm run build看看。沒報錯,使用瀏覽器打開dist/index.html看看。點擊連接沒反應?什麼狀況?莫慌,打開控制檯看看:

Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'file:///' cannot be created in a document with origin 'null' and URL

emmmm,咋整?別問我,真不是我乾的… 既然chrome很差使,就再看一眼safari下好很差用吧,同樣很差使,再看一眼報錯信息。

[Error] SecurityError: Blocked attempt to use history.pushState() to change session history URL from file:///demo/dist/index.html to file:///about. Paths and fragments must match for a sandboxed document.

好像safari的報錯更友好一些,咱們能夠清楚的看到,它在試圖改變連接,爲了安全起見,你認爲這麼作合理麼?豈不是拿個html能訪問計算機任何文件了?emmm,果真不合理。再看關鍵詞: Paths and fragments must match for a sandboxed document

那咱們就構建個沙盒環境吧。

webpack-dev-server

配置參考連接

安裝

yarn add webpack-dev-server --dev
複製代碼

修改配置

  • package.json中添加scripts

    "dev": "webpack-dev-server"
    複製代碼
  • webpack.config.js根節點中,添加:

    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 9000
      }
    複製代碼
  • 執行上面剛添加的srcripts

    npm run dev
    複製代碼
  • 瀏覽器中打開連接localhost:9000

功能沒問題,樣式無法忍,有木有?改!

  1. src中新建app.css文件,新增以下內容:

    .container {
      list-style: none;
    }
    複製代碼
  2. App.js中,添加以下代碼:

    import './app.css';
    複製代碼
  3. BasicExample中的ul應用樣式:

    <ul className="container">
    	<li><Link to="/">Home</Link></li>
    	<li><Link to="/about">About</Link></li>
    	<li><Link to="/topics">Topics</Link></li>
    </ul>
    複製代碼

這時,你會發現一個熟悉的錯誤。

You may need an appropriate loader to handle this file type.

此次咱們能夠很快的定位到,缺乏加載css相關的loader

再次與loader相遇

webpack相關文檔 雖然,webpack的文檔老是那麼的不及時,可是一些基礎性的東西,仍是能從中學到的。既然又一次遇到了loader,不妨此次咱們就完全搞明白什麼是loader,它爲咱們提供了什麼?

loader 用於對模塊的源代碼進行轉換。loader 可使你在 import 或"加載"模塊時預處理文件。所以,loader 相似於其餘構建工具中「任務(task)」,並提供了處理前端構建步驟的強大方法。loader 能夠將文件從不一樣的語言(如 TypeScript)轉換爲 JavaScript,或將內聯圖像轉換爲 data URL。loader 甚至容許你直接在 JavaScript 模塊中 import CSS文件!

看完這麼長一段,我總結了一句話,經過import來處理的文件,須要對應的loader。既然如此,那就一個一個安吧。

css-loader

安裝

yarn add style-loader css-loader --dev
複製代碼

配置

修改webpack.config.js中,module下的rules,就像添加babel-loader同樣,添加以下配置:

{
    test: /\.css$/,
    use: [
      'style-loader',
      'css-loader'
    ]
  }
複製代碼

關於css-loader這裏要再多提一句,當你不想對全局css進行污染,想經過如下方式使用時:

import styles from 'app.css';

<div className={styles.container} /> 複製代碼

請使用css module,webpack配置css module的方式也十分簡單:

'css-loader?modules&localIdentName=[name]-[hash:base64:5]',
複製代碼

css-loader調整成以上內容便可。

file-loader

處理各類圖標、圖片文件

安裝

yarn add file-loader --dev
複製代碼

配置

修改webpack.config.js中,module下的rules,添加以下配置:

{
	test: /\.(png|svg|jpg|gif)$/,
	use: [
	  'file-loader'
	]
}
複製代碼

字體文件依舊由file-loader處理,繼續添加配置:

{
	test: /\.(woff|woff2|eot|ttf|otf)$/,
	use: [
	  'file-loader'
	]
}
複製代碼

loader暫時添加到這裏,這時記住了沒?想讓webpack處理對應文件,就要有對應的loader

繼續刷新看咱們的demo工程,生效了。

初識Plugin

loader配置完,繼續按着文檔來吧,看看咱們還有什麼能夠了解的。

插件是 webpack 的支柱功能。webpack 自身也是構建於,你在 webpack 配置中用到的相同的插件系統之上!

插件目的在於解決 loader 沒法實現的其餘事。

html-webpack-plugin

管理輸出中有這麼一段:

若是咱們更改了咱們的一個入口起點的名稱,甚至添加了一個新的名稱,會發生什麼?生成的包將被重命名在一個構建中,可是咱們的index.html文件仍然會引用舊的名字。咱們用 HtmlWebpackPlugin 來解決這個問題。

OK,瞭解了它的目的,有用,裝!

安裝

yarn add html-webpack-plugin --dev

複製代碼

配置

webpack.config.js的根節點中添加plugins:

// 引入html-webpack-plugin
  const HtmlWebpackPlugin = require('html-webpack-plugin');
複製代碼
plugins: [
    new HtmlWebpackPlugin({
      title: 'Output Management'
    })
  ],
複製代碼

重啓下npm run dev,你會發現頁面空白了?臥槽,這不是坑麼?打開控制檯看一眼,Target container is not a DOM element.,再看一眼Elements選項卡中的內容,發現,咦。好像咱們的<div id="root"></div>神奇的消失了。 再看文檔,發現這麼一句話:

若是你想要了解更多 HtmlWebpackPlugin 插件提供的所有功能和選項,那麼你就應該多多熟悉 HtmlWebpackPlugin 倉庫。 其中的配置項中,template這項是這麼描述的: webpack require path to the template. Please see the docs for details

模板啊,咱們把dist/index.html中的文件挪出來,放到項目的根目錄下,而後再修改下webpack.config.js中的配置:

new HtmlWebpackPlugin({
  title: 'Demo',
  template: './index.html'
})
複製代碼

重啓下服務看看吧,npm run dev

頁面出來了,可是報了個錯:only one instance of babel-polyfill is allowed。 這又是什麼錯?咱們明明只有一個entry,爲何說引了屢次呢?打開Elements選項卡中,驚奇的發現,原來是咱們剛纔直接從dist目錄中挪的index.html中,還存在<script src="./my-first-webpack.bundle.js"></script>這麼一段script,刪掉,再重啓。大功告成。

clean-webpack-plugin

你可能已經注意到,因爲過去的指南和代碼示例遺留下來,致使咱們的 /dist 文件夾至關雜亂。webpack 會生成文件,而後將這些文件放置在 /dist 文件夾中,可是 webpack 沒法追蹤到哪些文件是實際在項目中用到的。

依然有用,依然裝!

安裝

yarn add clean-webpack-plugin --dev
複製代碼

配置

修改webpack.config.js: 引入CleanWebpackPlugin:

const CleanWebpackPlugin = require('clean-webpack-plugin');
複製代碼

添加plugins

new CleanWebpackPlugin(['dist']),
複製代碼

區分生產環境與開發環境

爲何要區分生產環境與開發環境?

開發環境(development)和生產環境(production)的構建目標差別很大。在開發環境中,咱們須要具備強大的、具備實時從新加載(live reloading)或熱模塊替換(hot module replacement)能力的 source map 和 localhost server。而在生產環境中,咱們的目標則轉向於關注更小的 bundle,更輕量的 source map,以及更優化的資源,以改善加載時間。因爲要遵循邏輯分離,咱們一般建議爲每一個環境編寫彼此獨立的 webpack 配置。

拆分webpack配置

按照官方教程,來進行拆分。在此,我更推薦新建config目錄,將配置統一放置config中,因此此時咱們的配置文件應該是:

config/webpack.common.js:

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

module.exports = {
  entry: ["babel-polyfill", "./index.js"],
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].[contenthash:12].js'
  },
  module: {
    rules: [
      { 
        test: /\.js$/, 
        exclude: /node_modules/,
        loader: "babel-loader?cacheDirectory" 
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          "css-loader"
        ]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'file-loader'
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(["dist"], {
      root: path.resolve(__dirname, "../"),
    }),
    new HtmlWebpackPlugin({
      title: 'Demo',
      template: './index.html'
    })
  ]
};
複製代碼

config/webpack.dev.js:

const merge  = require('webpack-merge');
const common = require('./webpack.common');
const path = require('path');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: path.resolve(__dirname, '../dist'),
    compress: true,
    port: 9000
  }
});
複製代碼

config/webpack.prod.js

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

module.exports = merge(common, {
  mode: 'production',
});
複製代碼

另外,package.json中的scripts也要進行相應的調整:

"build": "webpack --config config/webpack.prod.js",
"dev": "webpack-dev-server --config config/webpack.dev.js"
複製代碼

關於分離css

extract-text-webpack-plugin【4.0已廢棄】

tips: 這是一個從入門到放棄的Plugin,感興趣的話能夠繼續跟着操做,沒興趣請跳至下個小節。

它會將全部的入口 chunk(entry chunks)中引用的 *.css,移動到獨立分離的 CSS 文件。

安裝
yarn add extract-text-webpack-plugin --dev
複製代碼
配置

照着文檔中的🌰把配置貼進來,修爲webpack.config.js

const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  mode: "production",
  entry: ["babel-polyfill", "./index.js"],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { 
        test: /\.js$/, 
        exclude: /node_modules/,
        loader: "babel-loader?cacheDirectory" 
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'file-loader'
        ]
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
  ],
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000
  }
};
複製代碼

重啓服務的時候,你會發現報錯了?WTF?費了半天勁,結果還不能用?這時候咱們須要注意一點,就是它曾經確定是能用的,否則不能放到文檔上,這就體現出來webpack文檔落後了。既然如此,由於咱們當下使用的是webpack 4.x的版本,這時候先去ExtractTextWebpackPlugin的github上搜搜有沒有想過issue吧,關鍵詞webpack 4。 看到一個issue

@vasivas don't use extract-text-webpack-plugin for extract css, please use github.com/webpack-con…

居然還有這種操做,那就看看這個mini-css-extract-plugin

關於webpack,就引導到這裏,本文不是對webpack進行講解,更多關於webpack的部分,能夠看: @花褲衩 寫的文章:

手摸手,帶你用合理的姿式使用webpack4(上)

手摸手,帶你用合理的姿式使用webpack4(下)

最終咱們關於分離css的內容變成以下: webpack.common.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: ["babel-polyfill", "./index.js"],
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].[contenthash:12].js'
  },
  module: {
    rules: [
      { 
        test: /\.js$/, 
        exclude: /node_modules/,
        loader: "babel-loader?cacheDirectory" 
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader?modules&localIdentName=[name]-[hash:base64:5]',
        ]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'file-loader'
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(["dist"], {
      root: path.resolve(__dirname, "../"),
    }),
    new HtmlWebpackPlugin({
      title: 'Demo',
      template: './index.html'
    }),
  ]
};
複製代碼

webpack.prod.js

const merge  = require('webpack-merge');
const common = require('./webpack.common');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = merge(common, {
  mode: 'production',
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        sourceMap: true 
      }),
      new OptimizeCSSAssetsPlugin({})  // use OptimizeCSSAssetsPlugin
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:12].css',
      chunkFilename: '[name].[contenthash:12].css'  // use contenthash *
    })
  ]
});
複製代碼

webpack.dev.js

const merge  = require('webpack-merge');
const common = require('./webpack.common');
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: path.resolve(__dirname, '../dist'),
    compress: true,
    port: 9000
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ]
});
複製代碼

代碼分離

依舊看上面 @花褲衩 的文章,分的很細膩。在此咱們簡單分離:

webpack.common.js中修改:

const merge  = require('webpack-merge');
const common = require('./webpack.common');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = merge(common, {
  mode: 'production',
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        cache: true,
        parallel: true,
        sourceMap: true 
      }),
      new OptimizeCSSAssetsPlugin({})  // use OptimizeCSSAssetsPlugin
    ],
    runtimeChunk: {
      name: "manifest"
    },
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendors",
          priority: -20,
          chunks: "all"
        }
      }
    }
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:12].css',
      chunkFilename: '[name].[contenthash:12].css'  // use contenthash *
    })
  ]
});
複製代碼

OK,看似完美。

ReactBabelwebpack都有了,接下來就是爲了本身與團隊之間協做代碼的規範性,要經過下一個工具了。

Eslint

官網

安裝

npm install eslint -g #全局安裝eslint
複製代碼

初始化

eslint --init
複製代碼

選擇默認配置

? How would you like to configure ESLint? Use a popular style guide
? Which style guide do you want to follow? Airbnb (https://github.com/airbnb/javascript)
? Do you use React? Yes
? What format do you want your config file to be in? JavaScript
Checking peerDependencies of eslint-config-airbnb@latest
? The style guide "airbnb" requires eslint@^4.19.1. You are currently using eslint@5.2.0.
  Do you want to downgrade? Yes
複製代碼

在此直接選擇airbnb

調整配置

在初次安裝後,咱們發現咱們以前的App.js報錯了,這時咱們須要調整eslint相關的配置規則,來讓它更符合咱們預期的使用: 打開.eslintrc.js文件,調整內容以下:

module.exports = {
  "extends": "airbnb",
  "plugins":[
    "react",
    "jsx-a11y",
    "import"
  ],
  "rules": {
    "import/no-extraneous-dependencies": "off",
    "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
    "react/prop-types": 0
  }
};
複製代碼

更多eslint的使用姿式,還須要你我的進行探索。

引入ant-design

官網

安裝

yarn add antd
複製代碼

按需加載

若不想每次引用css時,可選用,在這裏使用babel-plugin-import

yarn add babel-plugin-import --dev
複製代碼

修改.babelrc文件中修改成:

{
  "presets": ["env", "react"],
  "plugins": [
    ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
  ]
}
複製代碼

試用

App.js中,進行引用:

import { DatePicker } from 'antd';

const Home = () => (
  <div> <h2> <DatePicker /> </h2> </div>
);
複製代碼

刷新後咱們發現,組件是顯示出來了,可是樣式並無生效。繼續去找解決方案: www.jianshu.com/p/603a61471… 這位老哥寫的很清楚了,原來是咱們的rules配置還有點瑕疵,根據內容調整以下:

{
    test: /\.css$/,
    exclude: /node_modules/,
    use: [
      MiniCssExtractPlugin.loader,
      'css-loader?modules&localIdentName=[name]-[hash:base64:5]',
    ],
  },
  {// antd樣式處理
    test: /\.css$/,
    exclude: /src/,
    use: [
      { loader: 'style-loader' },
      {
        loader: 'css-loader',
        options: {
          importLoaders: 1,
        },
      },
    ],
  },

複製代碼

調整完後,重啓webpack

最後

本文只作引子,讓你對前端工程化有必定的瞭解,更多的還需本身去根據關鍵字探索。

本人上上週搞得的基於百度地圖的封裝現已開源,歡迎加入一塊兒搞事情:

github

官網

相關文章
相關標籤/搜索