從0開始配置webpack和搭建一個React專案
先來說說react搭建:
1 官方文件上也有提供直接下載react包,但是修改webpack配置比較麻煩
npx create-react-app my-app cd my-app npm start
修改webpack配置需要執行
npm run eject
2 自行搭建一個專案並且配置webpack--主要記錄學習階段~總結的可能不太好,勉強看看,重點記錄一下第二種的方式
通過yarn管理包
- 下載yarn
yarn官網連結 安裝步驟都有的
- 在專案目錄下,執行yarn init
會出現我們的package.json檔案
-
安裝webpack
yarn add webpack --dev
-
新建webpack.config.js檔案,
貼官網示例:
const path = require('path'); module.exports = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'app.js' } };
命令列執行webpack會發現dist目錄
注意:yarn安裝過程中如果出錯,嘗試將yarn切換到淘寶映象再進行下載哦~,我安裝過程中出現過問題,切到這就沒問題了
yarn config set registry ' https://registry.npm.taobao.org '
-
安裝html-webpack-plugin
yarn add html-webpack-plugin --dev
按照文件操作,修改webpack.config.js使用html-webpack-plugin打包html檔案
再次執行webpack命令,會發現dist資料夾下面多了一個index.html
設定html-webpack-plugin的template模版,在src新建index.html,並且設定html內容
const path = require('path'); var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'app.js' }, plugins: [new HtmlWebpackPlugin( { template:'./src/index.html' } )] };
現在dist文件下面的index.html就是當前src下的index.html的模版了
-
安裝babel
yarn add babel-loader @babel/core @babel/preset-env
具體詳情見文件地址 在src/app.js中寫入一些ES6語法,再次執行webpack命令,dist/app.js進行了轉換
-
安裝react轉換 babel-preset-react
yarn add babel-preset-react --dev
修改webpack.config.js
const path = require('path'); var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/app.jsx' path: path.resolve(__dirname, 'dist'), filename: 'app.js' }, plugins: [new HtmlWebpackPlugin( { template:'./src/index.html' } )], module: { rules: [ { test: /\.m?jsx$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env','react'] } } } ] } };
-
安裝react
yarn add react react-dom
將src/app.js修改為app.jsx
import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('app') );
再執行webpack進行打包
如果出現Error: Plugin/Preset files are not allowed to export objects, only functions.錯誤
說明babel的版本不一致,我這邊是因為"babel-preset-react": "^6.24.1"預設裝的6版本,其他babel安裝的是7版本,所以統一升級到7或者降級到6
yarn add [email protected] --dev
這樣在進行打包,就可以了,這個時候開啟dist/index.html我們看到hello, world!說成功編譯了react
-
安裝style-loader
yarn add css-loader style-loader --dev
在webpack.config.js的rules中新增
{ test: /\.css$/, use: ['style-loader', 'css-loader'], },
在src下新建一個檔案index.css,隨便修改一點樣式
h1{ color:#F00; }
在app.jsx中引入
import './index.css'
再次執行webpack打包,重新整理dist/index.html
-
安裝ExtractTextWebpackPlugin外掛將css獨立到單獨的檔案
yarn add extract-text-webpack-plugin --dev
const path = require('path'); var HtmlWebpackPlugin = require('html-webpack-plugin'); const ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: './src/app.jsx', output: { path: path.resolve(__dirname, 'dist'), filename: 'app.js' }, module: { rules: [ { test: /\.m?jsx$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env','react'] } } }, { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }, ] }, plugins: [ new HtmlWebpackPlugin( { template:'./src/index.html' } ), new ExtractTextPlugin("index.css"), ], };
webpack.config.js配置如上
再次執行webpack,dist目錄下就多了一個index.css了~
注意:打包遇到Tapable.plugin is deprecated. Use new API on
.hooks
instead錯誤,原因是extract-text-webpack-plugin目前版本不支援webpack4執行:
yarn add extract-text-webpack-plugin@next --dev
-
安裝sass-loader
yarn add sass-loader --dev
在webpack.config.js中rules新增
{ test: /\.scss$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'sass-loader'] }) }
新建一個index.scss檔案
body{ background: #ccc; #app{ font-size: 22px; } }
在執行webpack會出現報錯Cannot find module 'node-sass'
需要安裝node-sass
yarn add node-sass --dev
打包,檢視index.html可以看到樣式應用上去了~
-
安裝url-loader處理圖片連結
yarn add url-loader file-loader --dev
在rules中加入:
{ test: /\.(png|jpg|gif)$/i, use: [ { loader: 'url-loader', options: { limit: 8192 } } ] }
專案中引入圖片,進行打包,這樣圖片資源也打包解析進去了~
-
新增解析字型rule
{ test: /\.(eot|svg|ttf|woff|woff2|otf)$/i, use: [ { loader: 'url-loader', options: { limit: 8192, name:'resource/[name].[ext]' } } ] },
-
新增webpack-dev-server
yarn add webpack-dev-server --dev
修改package.json新增
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"watch": "webpack --watch",
"start": "webpack-dev-server --open",
"build": "webpack-cli"
}
執行yarn run start啟動專案
yarn run build打包專案
最後附上當前為止修改後的webpack.config.js
const path = require('path'); const webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); const ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: './src/app.jsx', output: { path: path.resolve(__dirname, 'dist'), filename: './js/[name].[hash].js', chunkFilename: './js/[name].[hash].js', }, devServer: { port: 8080, proxy: { '/expo': { target: 'https://xxx', changeOrigin: true, pathRewrite: { '/expo': '/expo', }, secure: false, }, }, hot:true }, module: { rules: [ { test: /\.m?jsx$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env','react'] } } }, { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }, { test: /\.scss$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'sass-loader'] }) }, { test: /\.(png|jpg|gif|ico|jpeg)$/i, use: [ { loader: 'url-loader', options: { limit: 8192, name: "[name].[ext]", publicPath: "../images/", outputPath: "images/" } } ] }, { test: /\.(eot|svg|ttf|woff|woff2|otf)$/i, use: [{ loader: "file-loader", options: { name: "[name].[ext]", publicPath: "../fonts/", outputPath: "fonts/" } }] }, ] }, plugins: [ new HtmlWebpackPlugin( { template:'./src/index.html' } ), new ExtractTextPlugin("css/[name].css"), ], optimization:{ splitChunks:{ name:'common', filename:'js/base.js' } } };