從零搭建前端開發環境(零)——基礎篇:2.webpack生產與開發環境配置

接下來就要進行工程化的操作了,主要有兩個目的。

  1. 對靜態文件進行編譯、打包、壓縮、版本控制等優化操作;
  2. 構建一個便利的開發環境,比如熱加載、代理等。

這裏我們會用到webpack,輔以babel以及其他loader來處理js、css、圖片等靜態文件。對於各種loader的作用,本文會有一個大概的介紹,但不會展開說明,推薦看webpack文檔來做一個詳細的瞭解。

1、安裝webpack及各種loader和plugin

$ npm i -D webpack@3 webpack-dev-server@2 webpack-merge babel-core babel-loader babel-preset-env babel-preset-stage-2 css-loader style-loader less less-loader postcss-loader postcss-import postcss-url url-loader file-loader extract-text-webpack-plugin html-webpack-plugin

(注:截止至筆者寫作日,webpack4還不穩定,所以還是用webpack3,相應的需要webpack-dev-server@2)

說明:

  • babel-core、babel-loader、babel-preset-env、babel-preset-stage-2,babel相關負責將js編譯爲es5規範,要新增.babelrc配置文件。
  • css-loader、style-loader,負責css的編譯,webpack文檔裏可以找到。
  • postcss-loader、postcss-import、postcss-url,postcss負責給樣式添加瀏覽器前綴的兼容(如-webkit-),要新增.postcssrc.js配置文件。
  • less、less-loader樣式預編譯,當然也可以用sass。
  • url-loader,負責img、font等靜態文件編譯。
  • extract-text-webpack-plugin,負責將css提取爲單獨的文件。
  • html-webpack-plugin,負責向html模板中動態寫入靜態文件引用。

2、修改代碼

src/index.css重命名爲src/index.less

src/index.js(所有資源都用import引入,並把方法提取到util.js文件,方便後面的內容)

import { strReverse } from '@util';
import './index.less';
import logo from './assets/logo.jpg';

const $app = document.getElementById('app');

const strInput = 'Hello World';
const srtHolder = 'The result will be here...';
const strHtml = `
<img src="${logo}" alt="logo" />  
<h1>${strInput}</h1>  
<button id="do">Show the reverse of "${strInput}"</button>
<button id="reset">Do reset</button>
<p id="result">${srtHolder}</p>
`;

$app.innerHTML = strHtml;

const $result = document.getElementById('result');

document.getElementById('do').onclick = () => {
  $result.innerHTML = `The reverse of "${strInput}" is "${strReverse(strInput)}"`;
};
document.getElementById('reset').onclick = () => {
  $result.innerHTML = srtHolder;
};uti

新建src/util/index.js

export function strReverse(str) {
  return str.split('').reverse().join('');
}

index.html(去掉引用,webpack會自動加入)

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Hello World</title>
</head>
<body>
  <div id="app"></div>
</body>
</html>

3、配置webpack、babel、postcss

webpack默認的配置文件是webpack.config.js。但是通常的,我們會在開發環境引用webpack.dev.js,生產環境用webpack.prod.js,所以我們一步到位,建立config目錄,直接寫webpack.prod.js,webpack.dev.js並且用webpack-merge提取出它們的公共部分webpack.base.js,方便管理。這裏我們把jsx的坑先給填了,反正不影響。

config/webpack.base.js

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

const root = path.resolve(__dirname, '../');

module.exports = {
  entry: path.resolve(root, 'src'),
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
        },
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
        },
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Hello World',
      template: './index.html',
    }),
  ],
  resolve: {
    extensions: ['.js', '.jsx', '.json'],
    alias: {
      'src': path.resolve(root, 'src'),
      'util': path.resolve(root, 'src/util'),
    },
  },
};

config/webpack.dev.js

const path = require('path');
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const baseConfig = require('./webpack.base');

const root = path.resolve(__dirname, '../');

module.exports = webpackMerge(baseConfig, {
  output: {
    path: path.resolve(root, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.(css|less)$/,
        include: path.resolve(root, 'src'),
        use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'],
      },
    ],
  },
  devtool: 'cheap-module-eval-source-map',
  devServer: {
    contentBase: path.resolve(root, 'dist'),
    port: 9000,
    hot: true,
  },
  plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.HotModuleReplacementPlugin(),
  ],
});

config/webpack.prod.js

const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const webpackMerge = require('webpack-merge');
const baseConfig = require('./webpack.base');

const root = path.resolve(__dirname, '../');

module.exports = webpackMerge(baseConfig, {
  output: {
    path: path.resolve(root, 'dist'),
    filename: 'bundle.[chunkhash:10].js',
  },
  module: {
    rules: [
      {
        test: /\.(css|less)$/,
        include: path.resolve(root, 'src'),
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [{
            loader: 'css-loader',
            options: {
              minimize: true,
            },
          }, 'postcss-loader', 'less-loader'],
        }),
      },
    ],
  },
  devtool: '#source-map',
  plugins: [
    new UglifyJsPlugin({
      uglifyOptions: {
        compress: {
          warnings: false,
        },
      },
      sourceMap: true,
      parallel: true,
    }),
    new ExtractTextPlugin({
      filename: 'bundle.[contenthash:10].css',
      allChunks: true,
    }),
  ],
});

.babelrc

{
  "presets": [
    ["env",{ "modules": false }],
    "stage-2"
  ]
}

.postcssrc.js

module.exports = {
  "plugins": {
    "postcss-import": {},
    "postcss-url": {},
    "autoprefixer": {}
  }
}

然後,在package.json裏的scripts里加上prod和dev,分別對應生產和開發環境

"scripts": {
  "prod": "webpack --config config/webpack.prod.js",
  "dev": "webpack-dev-server --config config/webpack.dev.js --open"
},

4、試運行

先試試生產環境的命令,在命令行裏輸入

$ npm run prod

可以看到,生成了一個dist文件夾,這個就是我們以後會放到生產環境的文件夾。但是!!我們之前已經把它gitignore了。這樣做的目的是爲了不污染線上的環境,每次上線都是在線上打包,不會出現開發時的各種開發到一半的文件。

從今以後,我們想要看效果,就要點開dist/index.html文件來看了。打開試試吧。

再試試開發環境的命令

$ npm run dev

瀏覽器打開localhost:9000或127.0.0.1:9000。隨便改一改js或css試試,是不是自動刷新了。這在我們開發時會比較有好一些,現在整體的環境已經有一個完整的雛形了。別忘了提交git,記錄一下

$ git add .
$ git commit -m 'webpack init'

5、配置展示

全部變化可看筆者的github記錄,還是很清晰的。

package.json

{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "prod": "webpack --config config/webpack.prod.js",
    "dev": "webpack-dev-server --config config/webpack.dev.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "babel-preset-stage-2": "^6.24.1",
    "css-loader": "^0.28.11",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.1.0",
    "postcss-import": "^11.1.0",
    "postcss-loader": "^2.1.3",
    "postcss-url": "^7.3.1",
    "style-loader": "^0.20.3",
    "url-loader": "^1.0.1",
    "webpack": "^3.11.0",
    "webpack-dev-server": "^2.11.2",
    "webpack-merge": "^4.1.2"
  }
}

項目結構

demo
  |- config
    |- webpack.base.js
    |- webpack.dev.js
    |- webpack.prod.js
  |- src/
    |- assets/
     |- logo.jpg
    |- index.css
    |- index.js
  |- .babelrc
  |- .gitignore
  |- .postcssrc.js
  |- index.html
  |- package.json


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章