webpack4構建前端專案
阿新 • • 發佈:2019-01-06
在使用webpack 4.x版本構建前端專案的時候,遇到了一些坑點,這裡做一下記錄,詳細內容見註釋。
1、專案目錄:
2、基本配置內容
webpack.base.config.js
'use strict'; const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //用於在構建前清除dist目錄中的內容 const CleanWebpackPlugin = require('clean-webpack-plugin'); let baseWebpackConfig = { // 指定找入口檔案所在資料夾 context: path.resolve(__dirname, '../src/test'), // 這裡是我做test的一個單獨資料夾 entry: './index.js', output: { // 打包出的檔名 filename: '[name].bundle.[hash:8].js', // 打包出的檔案輸出路徑 path: path.resolve(__dirname, '../dist'), publicPath: "/" // 編譯後模板檔案地址 }, module: { rules: [ { test: /\.(js|jsx)$/i, // use: ['babel-loader'], loader: 'babel-loader', exclude: /(node_modules|bower_components)/, options: { // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true, plugins: ['react-hot-loader/babel'], } }, { test: /\.(less|css)$/i, use:['css-hot-loader',MiniCssExtractPlugin.loader,"css-loader","less-loader",{ loader: "postcss-loader", options: { ident: 'postcss', plugins: () => [ require('autoprefixer')("last 100 versions") ] } }] }, { test: /\.(png|jpe?g|gif|svg|ico)(\?.*)?$/, use: [{ loader: 'url-loader', options: { limit: 10000, // 大於就用檔案形式,小於就壓縮成base64 name: 'img/[name].[hash:7].[ext]' } }] }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, use: [{ loader: 'url-loader', options: { limit: 10000, name: 'media/[name].[hash:7].[ext]' } }] }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: [{ loader: 'url-loader', options: { limit: 10000, name: 'fonts/[name].[hash:7].[ext]' } }] } ] }, plugins: [ //用於在構建前清除dist目錄中的內容 new CleanWebpackPlugin(['dist'], { root: path.resolve(__dirname, '../'), // 根目錄 verbose: true, // 開啟在控制檯輸出資訊 }), // dist目錄下生成html模板檔案 new HtmlWebpackPlugin({ template: './index.html' }), // 樣式程式碼分離 // new ExtractTextWebpackPlugin('styles.css'), // (webpack4廢棄) new MiniCssExtractPlugin({ filename: "[name].css", // **注意**這裡不能使用hash,否則無法實現熱跟新,如果有hash需要,可以開發環境和生產環境分開配置成[name].[chunkhash:8].css chunkFilename: "[id].css" // 構建時生成的檔名 }) ], resolve: { // 設定自動解析的擴充套件 extensions: ['.web.js', '.js', '.json', '.jsx', '.less', '.css'], // 設定路徑別名 alias: { '@': path.resolve(__dirname, '../src/') } } }; module.exports = baseWebpackConfig;
3、本地開發環境dev伺服器配置
webpack.dev.config.js
'use strict'; const PORT = 3000; const path = require('path'); const webpack = require('webpack'); const merge = require('webpack-merge'); const baseWebpackConfig = require('./webpack.base.config'); const OpenBrowserWebpackPlugin = require('open-browser-webpack-plugin'); let webpackDevServerConfig = { mode: 'development', // 入口配置 entry: [ 'babel-polyfill', // 原生支援 'react-hot-loader/patch', // 區域性更新 './index.js' ], devtool: 'cheap-module-source-map', plugins: [ // 美化 console 輸出 new webpack.NamedModulesPlugin(), // 開啟全域性的模組熱替換(HMR) new webpack.HotModuleReplacementPlugin(), // 編譯完成在再瀏覽器開啟專案 new OpenBrowserWebpackPlugin({url: `http://0.0.0.0:${PORT}`}), // {url: `http://localhost:${PORT}`} // 編譯時定義全域性變數,用於判斷執行環境 | 配合cross_env外掛使用,它是執行跨平臺設定和使用環境變數的指令碼 new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV) } }) ], devServer: { // hot: true, hotOnly: true, // 只熱替換,不自動重新整理 port: PORT, inline: true, // 實時重新整理 publicPath: baseWebpackConfig.output.publicPath, host: '0.0.0.0', // 是否關閉用於DNS重繫結的HTTP請求的host檢查,它通常用於搭配 --host 0.0.0.0 使用, // 因為你想要其它裝置訪問你本地的服務,但訪問時是直接通過 IP 地址訪問而不是 HOST 訪問,所以需要關閉 HOST 檢查。 disableHostCheck: true, // 把專案根目錄下的src目錄設定成DevServer伺服器的檔案根目錄 contentBase: path.resolve(__dirname, 'src'), // 可以保證類似http://localhost:8080/aa的請求返回跟http://localhost:8080/一樣的頁面, // 這樣才能用同一個js根據路徑的不同去往不同的路由 historyApiFallback: true }, // dev環境打包的單個js檔案可能過大,通過該方式取消警告 performance: { hints: process.env.NODE_ENV === 'development' ? false : 'warning' } }; module.exports = merge(baseWebpackConfig, webpackDevServerConfig)
4、生產打包配置
webpack.build.config.js
'use strict'; const merge = require('webpack-merge'); const webpack = require('webpack'); const baseWebpackConfig = require('./webpack.base.config.js'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); let webpackBuildConfig = { mode: 'production', // 入口配置 entry: [ 'babel-polyfill', // 瀏覽器原生支援 'react-hot-loader/patch', // 區域性更新 './index.js' ], plugins: [ new UglifyJSPlugin({ sourceMap: true }), // 編譯時定義全域性變數,用於判斷執行環境 new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV) } }) ] }; module.exports = merge(baseWebpackConfig, webpackBuildConfig);
5、package.json對scripts屬性配置
核心程式碼:
"test": "echo \"Error: no test specified\" && exit 1",
"start": "npm run dev",
"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.dev.config.js",
"build": "cross-env NODE_ENV=production webpack -p --config build/webpack.build.config.js"
package.json
6、test目錄下的一些測試檔案
<1>、 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test-html</title>
</head>
<body>
<div id="test"></div>
</body>
</html>
<2>、index.js
import React from 'react'
import ReactDom from 'react-dom'
import { AppContainer } from 'react-hot-loader';
import './style.less'
import bigImg from './imgs/big-test.png'
import smallImg from './imgs/small-test.png'
let html = <div className='wrapper'>
<h1 className='test'>hello webpack!</h1>
<span>16.4kb---></span><img src={bigImg} />
<span>6.09kb---></span><img src={smallImg} />
</div>
ReactDom.render(
<AppContainer>
{html}
</AppContainer>,
document.getElementById('test')
)
// HMR 介面
if (module.hot) {
// 實現熱更新
module.hot.accept()
}
<3>、style.less
.wrapper{
display: flex;
flex-direction: column;
align-items: center;
.test{
border-radius: 5px;
flex: 1;
color: black
}
}
7、.babelrc的配置
{
"presets": [
[
"es2015",
{
"modules": false
}
],
"react",
"stage-0"
],
"plugins": [
"react-hot-loader/babel",
"transform-runtime"
]
}