工欲善其事,必先利其器。單頁面應用的開發和生產環境涉及文件的編譯、壓縮、打包、合併等,目前前端最流行的莫過於 webpack
。爲了深刻了解 webpack
以及其相關插件,咱們決定不採用腳手架,本身來搭建基於 webpack
的開發和生產環境。css
nodejs的安裝: 移步官網html
建議使用nvm來管理nodejs的版本
安裝nvm前端
咱們使用的是 webpack@2.X.X
,建議讀完 官方文檔 對她有個大概的瞭解。html5
webpack-dev-server 用 webpack-dev-server
來進行開發環境下面的自動打包編譯,包括熱更新等等。固然也能夠本身經過 webpack-dev-middleware
來自定義一個開發服務器。具體能夠參考 webpack-dev-server
的源代碼。node
webpack-hot-middleware 向入口文件中添加一個 client
文件,當文件變化時,服務器端能夠經過 socket
事件來通知這個 client
來實現熱更新。注:這個事件是 EventSource事件。 webpack-dev-server
已經將這個中間件封裝到內部,咱們只須要進行配置便可。react
babel-loader 編譯 es6
代碼。移步官網。值得一提的是 es2016
, es2017
, env
等是對已經或者將要被加入 JS這門語言的提案進行預編譯,而 stage-0
, stage-1
, stage-2
等是對未來可能加入立案裏面的語法的預編譯。webpack
extract-text-webpack-plugin 樣式文件默認會被 webpack 打包到js文件中。這個插件能夠提取出這些被打包進入的文件。git
固然咱們用到的不僅是這些,你能夠到npm官網或者github上面找到這些plugin、loader的詳細用法es6
blog ├─ dist # 輸出目錄 ├─ task # 這裏來放webpack處理和配置文件 ├─ src | ├─ components # 組件 | └ index.js # 入口文件 | package.json
在 src/
目錄下新建入口文件 index.js
github
import React from 'react' import ReactDOM from 'react-dom' // 這裏須要藉助 webpack 的同名功能來代替繁瑣的相對路徑 import HomeComponent from 'components/Home' ReactDOM.render(<HomeComponent />, document.getElementById('root'))
在 src/component/
目錄下新建 Home.js
模塊
import React, { Component } from 'react' export default class Home extends Component { render(){ return <div>Hello world!</div> } }
在 src/
目錄下新建 index.html
文件來做爲單頁面的HTML文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>blog</title> </head> <body> <div id="root"></div> </body> </html>
如今咱們來添加 webpack
的配置文件來對這些文件進行打包、編譯
在 task/
目錄下新建 config.js
文件
const path = require('path') const webpack = require('webpack') const webpackMerge = require('webpack-merge') const HtmlWebpackPlugin = require('html-webpack-plugin') const base = { // 上下文環境,相對路徑都基於這個路徑 context: path.resolve(__dirname, '..'), entry: './src/index.js', output: { path: path.resolve(__dirname, '../dist'), publicPath: '/assets/', filename: '[name].js' }, module: { rules: [ { test: /\.js$/, include: path.resolve(__dirname, '../src'), exclude: [ /node_modules/ ], use: [ 'react-hot-loader', { loader: 'babel-loader', options: { presets: ['env', 'react'], plugins: [ "add-module-exports", "transform-runtime" ] } } ], } ] }, resolve: { extensions: ['.js', '.jsx'], alias: { // 這裏對應着入口文件中 component 的同名配置 components: path.resolve(__dirname, '../src/components') } } } const dev = webpackMerge(base, { output: { publicPath: '/' }, // 源文件的 source map devtool: "source-map", plugins: [ new webpack.HotModuleReplacementPlugin(), new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"development"' } }), new HtmlWebpackPlugin({ template: './src/index.html', filename: 'index.html', inject: true }) ], devServer: { // 開啓熱加載,須要 hmr 的支持 hot: true, contentBase: path.resolve(__dirname, '../dist'), // 這個路徑必定要和 output 的 publicPath 的屬性一致 publicPath: '/', } }) const prod = webpackMerge(base, { }) // 根據 NODE_ENV 來決定輸出的配置 module.exports = process.env.NODE_ENV === 'production' ? prod : dev
在項目跟路徑下執行
export NODE_ENV=development && webpack-dev-server --config ./task/config.js
export NODE_ENV=development
設置 NODE_ENV
這個環境變量爲 development
有助於咱們區分開發環境和生產環境。這是mac下面的設置方法,windows 能夠自行搜索
編譯成功,而且頁面輸出 Hello world!
表示配置跑通...
在 package.json
添加
{ "scripts": { "dev": "export NODE_ENV=development && webpack-dev-server --config ./task/config.js --progress --colors --hotOnly" } }
webpack-merge
來覆蓋 output.publicPath
屬性若是 devServer.publicPath = output.publicPath = '/assets/'
的話,那麼在瀏覽器中打開 localhost:80XX/assets/index.html
才能訪問到 index.html
文件,而將 publicPath = '/'
就直接經過 localhost:80XX
就能夠訪問。
loader
的配置其中 include
, exclude
就很少說
{ use: [ 'react-hot-loader', { loader: 'babel-loader', options: { presets: ['env', 'react'], plugins: [ "add-module-exports", "transform-runtime" ] } } ], }
react-hot-loader 會解決更改 react 組件的時 webpack 熱更新直接刷新頁面的問題。
babel-presets-react
用來處理 react 的 jsx 語法
babel-plugin-add-module-exports babel@6
會將es6的語法
// home.js export default 'foo'
轉化爲
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = 'foo';
因此在使用 commonjs
的語法 require('./home')
時,獲得的是{default: 'foo'}
,因此:
var home = require('./home').default console.log(home) // 'foo'
這個插件能夠避免這一現象
這裏解釋一下使用 html-webpack-plugin
的必要性。
其實徹底能夠扔一個靜態的 index.html
給 webpack-dev-server
,這裏面只須要有個 <script src="bundle.js"></script>
標籤,就能夠成功來進行訪問。可是更多的時候咱們會定製打包文件的名稱: output.filename: '[name]-[hash].js'
,編譯以後 webpack
會輸出一個相似於這樣的文件 bundle-fb9758acf17b2b5fb653.js
,那麼你每次打包都須要去更改那個src屬性,而 html-webpack-plugin
能夠幫你解決這些事情
在 src/component/
下新建 Home.module.less
@color: green; :global { body { background-color: red; } } .wrap { color: @color; }
在同級目錄下的 Home.js
組件中引入這個 less 文件
import React, { Component } from 'react' import Style from './home.module.less' export default class Home extends Component { render(){ return <div className={Style.wrap}>Hello world!</div> } }
咱們沒有在 task/config.js
下增長對 less
文件的支持,確定會報錯的。先說一下爲何要以 .module.less
標識 less
文件,只會咱們會引入 babel-plugin-import
對樣式庫 antd
進行按需加載,因爲 antd
源代碼中的樣式文件也是用 less
寫的,這樣會致使這些文件被做爲 css-module
處理,因此加以區別,這是參考 atool-build 的配置。
在 task/config.js
文件新增 :
const ExtractTextPlugin = require('extract-text-webpack-plugin') const autoprefixer = require('autoprefixer') const runsack = require('rucksack-css') const theme = require('../theme.js')() const postcssPlugins = () => [ runsack(), // 可選 autoprefixer({ browsers: ['last 2 versions', 'Firefox ESR', '> 1%', 'ie >= 8', 'iOS >= 8', 'Android >= 4'], }), ] // 在base.module.rules裏增長 { test: /\.module\.less$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', // 將下面處理過的文件插入html中 use: [ { loader: 'css-loader', // 開啓對css-module的支持,並定義className的輸出格式 options: { modules: true, importLoaders: 1, localIdentName: '[name]__[local]___[hash:base64:5]'} }, { loader: 'postcss-loader', options: { plugins: postcssPlugins } }, { loader: 'less-loader', // 覆蓋默認的全局配置 options: {"modifyVars": theme} } ] }) }, // 在 base.plugins 裏增長 new ExtractTextPlugin({ filename: 'css/[name]-[hash].css', }),
其餘的 loader 和 webpack plugin 就再也不贅述, 移步文檔
還要注意的是
less-loader
中的配置選項,{"modifyVars": theme}
,這能夠覆蓋less
文件的配置,能夠用來自定義樣式庫antd
, 繼續查看
在項目根目錄下新建 theme.js
module.exports = function(){ return {} }
別忘記安裝配置文件裏面用到的 loader、pulgins… = =
安裝 less-loader
記得把 less
也裝上,它的文檔也是有強調的哦!
基礎的環境配置就到這裏。生產環境你能夠自行配置,以後我會在後面的文章中列出來。
你能夠在這個倉庫查看 這第一次 commit 哦!下面皆能夠愉快的作本身的博客了!