摘要:優(yōu)化代碼拆分從入口文件開(kāi)始,遞歸地構(gòu)建了整個(gè)應(yīng)用的模塊依賴圖表,然后通常會(huì)將所有的模塊打包成一個(gè)。
如果你還不知道什么是React,請(qǐng)點(diǎn)擊這里
github源碼
如果你還不知道什么是ECMAScript,請(qǐng)點(diǎn)擊這里
如果你還不知道什么是Node.js,請(qǐng)點(diǎn)擊這里
下載Node.js并安裝;接著打開(kāi)windows命令行窗口分別輸入node -v及npm -v
如下圖所示,node和npm均顯示出版本號(hào)則表示安裝成功!
如果你還不知道什么是npm,請(qǐng)點(diǎn)擊這里
在你想要放置該項(xiàng)目代碼的任何地方新建一個(gè)文件夾,并命名為react-template,接著打開(kāi)該文件夾路徑下windows命令行窗口輸入npm init,接著根據(jù)提示依次輸入:
package name:項(xiàng)目名稱(默認(rèn)是文件夾名稱)
version:版本號(hào)(默認(rèn)是1.0.0)
description:項(xiàng)目描述
entry point:項(xiàng)目入口文件(默認(rèn)是index.js)
test command:測(cè)試命令
git repository:git遠(yuǎn)程倉(cāng)庫(kù)地址
keywords:項(xiàng)目關(guān)鍵詞
author:作者
license:開(kāi)源許可聲明
初始化完成后,項(xiàng)目根目錄會(huì)自動(dòng)生成package.json文件,這就是項(xiàng)目的npm配置文件了。
使用webpack4搭建自動(dòng)化開(kāi)發(fā)環(huán)境如果你還不知道什么是webpack,請(qǐng)點(diǎn)擊這里,并且本人強(qiáng)烈建議把該頁(yè)內(nèi)容耐心讀完。
webpack是一個(gè)靜態(tài)資源模塊打包器,并且webpack支持多種不同的模塊系統(tǒng),我們主要用到以下三個(gè):
es6模塊系統(tǒng)
node平臺(tái)的CommonJS模塊系統(tǒng)
sass/less的模塊系統(tǒng)
一、使用npm安裝webpack首先,給package.json文件寫入兩個(gè)屬性:
這兩個(gè)屬性都是用來(lái)維護(hù)項(xiàng)目的本地依賴包列表的,但是devDependencies比較特殊,它只是開(kāi)發(fā)環(huán)境的依賴,當(dāng)構(gòu)建生產(chǎn)環(huán)境代碼時(shí),這些包的代碼會(huì)被舍去。
接著,給devDependencies寫入webpack的依賴:
鍵值對(duì):key為包名,value為版本號(hào)
{ ... "devDependencies": { "webpack": "^4.12.0", "webpack-cli": "^3.0.8" ... } }
命令行npm install或npm i,這個(gè)命令會(huì)根據(jù)dependencies和devDependencies的配置去檢查是否所有的依賴包都在本地安裝了,若沒(méi)有則會(huì)安裝對(duì)應(yīng)的包到本地。
如果你對(duì)npm命令行不了解,可以看這里
如果你對(duì)npm的“全局”和“本地”的概念不是很清楚,例如:上文提到的本地依賴包,可以看這里
安裝成功后,項(xiàng)目根目錄下會(huì)生成一個(gè)node_modules文件夾,它就是本地依賴包的倉(cāng)庫(kù),你可以在它的里面找到包webpack和webpack-cli。
特別地,還需要全局安裝webpack,否則命令行窗口認(rèn)不到 webpack 的命令。
$ npm i -g webpack webpack-cli二、編寫webpack4配置文件
新建react-template/src文件夾,并在里面新建文件index.js
新建react-template/build文件夾,接著在build文件夾里再新建兩個(gè)文件:
webpack.base.js:基礎(chǔ)配置文件(開(kāi)發(fā)和生產(chǎn)共用)
webpack.dev.js:自動(dòng)化開(kāi)發(fā)環(huán)境的配置文件
webpack.pro.js:構(gòu)建生產(chǎn)環(huán)境代碼配置文件
關(guān)于webpack配置的詳細(xì)內(nèi)容,請(qǐng)看這里
webpack基礎(chǔ)配置配置文件通常是一個(gè)CommonJS規(guī)范的模塊,輸出一個(gè)JavaScript Object
// __dirname表示當(dāng)前目錄,path.resolve()可以防止不同操作系統(tǒng)之間的文件路徑問(wèn)題,并且可以使相對(duì)路徑按照預(yù)期工作 module.exports = { /** * 項(xiàng)目入口文件 */ entry: path.resolve(__dirname, "../src/index.js") // ...省略其它選項(xiàng) }
module.exports = { //... /** * 指定打包后的 bundle 如何輸出 * 特別說(shuō)明: * 1. bundle是指多個(gè)模塊打包在一起,產(chǎn)生的新文件。bundle 一般由html文件通過(guò) script 標(biāo)簽加載 */ output: { // 打包后的 bundle 的生成位置(E:/react-template/dist/) path: path.resolve(__dirname, "../dist/"), // 主 bundle(E:/react-template/dist/js/main.js) filename: "js/main.js", // chunk: 多帶帶拆分出來(lái)的 bundle,name即為chunk的名稱 chunkFilename: "js/[name].js", // publicPath + chunkFilename 為打包后生成的html文件請(qǐng)求 chunkFile 的路徑 // publicPath + 圖片的URL 為打包后生成的html文件請(qǐng)求圖片的路徑,其他靜態(tài)資源文件同理 publicPath: "/" } //... }
module.exports = { //... /** * 如何解析模塊路徑 */ resolve: { // 指定要解析的文件擴(kuò)展名 extensions: [".web.js", ".jsx", ".js", ".json"], // 模塊路徑別名 alias: {} }, //... }
module.exports = { //... /** * 指定如何處理(編譯)各種類型的模塊 * 特別說(shuō)明: * 1. webpack提供了豐富的針對(duì)不同類型模塊的loader,你可以使用loader對(duì)模塊進(jìn)行預(yù)處理或者對(duì)模塊的 * 源代碼進(jìn)行轉(zhuǎn)換(編譯) * 2. 常見(jiàn)的模塊類型:js, jsx, css, scss, less, json, png, git, jpg */ module: { /** * 各種類型模塊的處理規(guī)則 * 特別說(shuō)明: * 1. use屬性表示模塊使用什么loader * 2. 模塊可以使用多個(gè)loader,處理順序?yàn)閡se屬性的數(shù)組的第一個(gè)到最后一個(gè) */ rules: [ // 圖片文件小于8192byte時(shí),轉(zhuǎn)換為base64字符串 { test: /.(gif|png|jpg|jpeg|woff|woff2|eot|ttf|svg)(?t=d+)?$/, exclude: /node_modules/, use: ["url-loader?limit=8192"] }, /** * 將js和jsx模塊的源代碼編譯成瀏覽器能正常執(zhí)行的代碼 * 特別說(shuō)明: * 1. eslint是一個(gè)代碼檢查工具,中文官網(wǎng):https://cn.eslint.org/ * 一般我們會(huì)在項(xiàng)目根目錄下為eslint創(chuàng)建一個(gè)配置文件 .eslintrc.json ,關(guān)于eslint * 的配置,祥見(jiàn):附錄/eslint-loader配置文件 * 2. babel是一個(gè)JavaScript編譯器,它能夠?qū)g覽器尚未實(shí)現(xiàn)的新一代的ES語(yǔ)法轉(zhuǎn)換成瀏覽器 * 已實(shí)現(xiàn)的語(yǔ)法,比如我們現(xiàn)在廣泛使用的es6和部分es7語(yǔ)法和新的內(nèi)置對(duì)象,其實(shí)瀏覽器并沒(méi) * 有完全實(shí)現(xiàn),但是有了babel,我們完全可以放心使用它們。 * 3. 一般我們會(huì)在項(xiàng)目根目錄下為babel創(chuàng)建一個(gè)配置文件 .babelrc ,關(guān)于babel的配置,詳 * 見(jiàn):附錄/babel-loader配置文件 */ { enforce: "pre", test: /.(js|jsx)?$/, exclude: /node_modules/, use: [{ loader: "eslint-loader", options: { emitError: true, emitWarning: true, failOnError: true } }] }, { test: /.(js|jsx)?$/, exclude: /node_modules/, use: ["babel-loader"] }, /** * 處理css模塊 * loader說(shuō)明: * 1. style-loader 將css文件以 * * 的形式插入到html文件 * 2. css-loader 處理css的 @import語(yǔ)句 與 url() ,同時(shí)壓縮代碼 * 3. postcss-loader 對(duì)css做一些加工處理,具體的配置放在postcss.config.js,比如給 * css自動(dòng)添加瀏覽器廠商前綴。如果不知道css瀏覽器廠商前綴的,請(qǐng)自行百度。 */ { test: /.(css)?$/, use: [ "style-loader/url", { loader: "css-loader", options: { minimize: { safe: true, discardComments: { removeAll: true } } } }, "postcss-loader" ] }, /** * 處理less模塊 * 特別說(shuō)明: * 1. Less 是一門 CSS 預(yù)處理語(yǔ)言,它擴(kuò)展了 CSS 語(yǔ)言,增加了變量、Mixin、函數(shù)等特性, * 使 CSS 更易維護(hù)和擴(kuò)展。 * 2. Less中文網(wǎng):http://lesscss.cn/ */ { test: /.less$/, use: ["style-loader", "css-loader", "less-loader"] }, /** * 處理scss模塊 * 特別說(shuō)明: * 1. sass與less類似,也是一門css預(yù)處理語(yǔ)言。 */ { test: /.scss$/, exclude: /node_modules/, use: [ "style-loader", "css-loader", "postcss-loader", "sass-loader" ] } ] } //... }
module.exports = { //... /** * 外部擴(kuò)展 * 有時(shí)候你可能不想把某個(gè)第三方 library 打包進(jìn)你的 package 里,而是希望 library 做為外部依賴; * 比如通過(guò) script 標(biāo)簽來(lái)加載此 library , externals 這個(gè)選項(xiàng)可以幫到你。 */ externals: { "react": { commonjs: "React", commonjs2: "React", amd: "React", root: "React" }, "react-dom": { commonjs: "ReactDOM", commonjs2: "ReactDOM", amd: "ReactDOM", root: "ReactDOM" } } //... }
module.exports = { //... /** * 優(yōu)化 */ optimization: { /** * 代碼拆分 * 從入口文件開(kāi)始,webpack 遞歸地構(gòu)建了整個(gè)應(yīng)用的模塊依賴圖表(dependency graph),然后通 * 常會(huì)將所有的模塊打包成一個(gè) bundle。但是有兩種情況需要把一些模塊拆分成多帶帶的 bundle: * 1. 通過(guò) import() 函數(shù)導(dǎo)入的模塊,這些模塊不會(huì)被打包進(jìn)主 bundle 里,而是拆分為多帶帶的 * bundle,等待 import() 函數(shù)執(zhí)行,再去異步加載。 * import() 函數(shù)介紹:https://juejin.im/entry/58ba3308a22b9d005ede7565 * 2. 有的模塊由于被多個(gè)不同的 bundle 依賴,所以這幾個(gè) bundle 里都會(huì)有該模塊的代碼;這時(shí)就 * 需要將這種模塊也多帶帶拆分出來(lái),避免重復(fù)加載相同的模塊。 */ splitChunks: { chunks: "all", minSize: 30000, minChunks: 2, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: "~", name: true, cacheGroups: { default: false, vendor: { name: "vendor", priority: 99 } } } } }
以上就是webpack的基礎(chǔ)配置了。我們還需要把配置中用到的loader及相關(guān)的模塊下載到本地。
其中,由于:
babel-loader依賴以下列出的package:
babel-core
babel-runtime
babel-plugin-transform-runtime
babel-plugin-external-helpers
babel-preset-env
babel-preset-react
babel-plugin-import
babel-plugin-syntax-dynamic-import
babel-plugin-transform-class-properties
babel-plugin-transform-decorators-legacy
eslint-loader依賴以下列出的package:
eslint
babel-eslint
eslint-plugin-react
less-loader依賴 less
postcss-loader依賴 postcss
把上面列出的package寫入package.json的dependencies和devDependencies
{ "dependencies": { "babel-runtime": "^6.26.0" }, "devDependencies": { "autoprefixer": "^9.1.5", "babel-core": "^6.26.3", "babel-eslint": "^9.0.0", "babel-loader": "^7.1.5", "babel-plugin-external-helpers": "^6.22.0", "babel-plugin-import": "^1.9.1", "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators-legacy": "^1.3.5", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", "css-loader": "^1.0.0", "eslint": "^5.6.0", "eslint-loader": "^2.1.1", "eslint-plugin-react": "^7.11.1", "file-loader": "^2.0.0", "less": "^3.8.1", "less-loader": "^4.1.0", "node-sass": "^4.9.0", "path": "^0.12.7", "postcss": "^6.0.22", "postcss-loader": "^3.0.0", "react-hot-loader": "^4.3.8", "sass-loader": "^7.0.3", "style-loader": "^0.23.0", "url-loader": "^1.1.1", "webpack": "^4.12.0", "webpack-cli": "^3.1.0", "webpack-merge": "^4.1.4" } }
接著
$ npm installwebpack自動(dòng)化開(kāi)發(fā)環(huán)境配置
上一步的基礎(chǔ)配置都完成之后,實(shí)際上webpack已經(jīng)可以正常工作了,你可以寫一些測(cè)試模塊,然后在src/index.js引入,用命令行運(yùn)行webpack
$ webpack --config ./build/webpack.base.js --mode=development
但是這個(gè)過(guò)程是純手動(dòng)的,我們可以使用一些webpack plugin來(lái)讓某些動(dòng)作自動(dòng)化,以此來(lái)提高工作效率。
下面是webpack開(kāi)發(fā)模式的配置文件:
var base = require("./webpack.base.js"), // merge() 合并配置選項(xiàng) merge = require("webpack-merge"), HtmlWebpackPlugin = require("html-webpack-plugin"), copyWebpackPlugin = require("copy-webpack-plugin"); module.exports = merge(base, { // 開(kāi)發(fā)模式 mode: "development", devtool: "#cheap-module-eval-source-map", // webpack plugin -> https://webpack.docschina.org/plugins/ plugins: [ // 復(fù)制無(wú)需參與構(gòu)建的文件到輸出位置 new copyWebpackPlugin([ { from: "src/js_modules/react/dev/react.js", to: "js/" }, { from: "src/js_modules/react-dom/dev/react-dom.js", to: "js/" }, { from: "img/**/*.*", to: "" } ]), // 自動(dòng)在輸出位置創(chuàng)建html文件,并在html文件自動(dòng)注入加載bundle的script標(biāo)簽或link標(biāo)簽 new HtmlWebpackPlugin({ filename: "index.html", template: "index.html", chunks: ["main", "vendor"], inject: true, chunksSortMode: "auto" }) ] });
光是能復(fù)制或自動(dòng)創(chuàng)建文件還不夠,我們希望在開(kāi)發(fā)過(guò)程中,當(dāng)我們修改代碼之后,webpack能夠監(jiān)聽(tīng)變更的文件自動(dòng)增量編譯,也希望瀏覽器能實(shí)時(shí)響應(yīng)我們的代碼(文件)變更,并自動(dòng)變化或重載。要實(shí)現(xiàn)這個(gè)需求,我們需要使用express,并結(jié)合webpack-dev-middleware和webpack-hot-middleware來(lái)搭建一個(gè)開(kāi)發(fā)服務(wù)器。順便提一句我個(gè)人比較推薦使用gulp來(lái)作為項(xiàng)目工程化的流程管理工具,所以啟動(dòng)開(kāi)發(fā)服務(wù)器我是作為一個(gè) gulp任務(wù) 來(lái)編寫的,首先在根目錄創(chuàng)建一個(gè)gulpfile.js,寫入下面的代碼:
var gulp = require("gulp"), gutil = require("gulp-util"), express = require("express"), webpack = require("webpack"), webpackDevMiddleware = require("webpack-dev-middleware"), webpackHotMiddleware = require("webpack-hot-middleware"), history = require("connect-history-api-fallback"), opn = require("opn"); // 開(kāi)發(fā)服務(wù)器 gulp.task("dev", function() { var webpackDevConfig = require("./build/webpack.dev.js"); webpackDevConfig.entry = [ "webpack-hot-middleware/client?noInfo=true" ].concat([webpackDevConfig.entry]); webpackDevConfig.plugins = webpackDevConfig.plugins.concat([ new webpack.HotModuleReplacementPlugin() ]); var devCompiler = webpack(webpackDevConfig); var devMiddleware = webpackDevMiddleware(devCompiler, { publicPath: webpackDevConfig.output.publicPath, stats: { chunks: false, colors: true, timings: true, source: true, cachedAssets: false }, watchOptions: { ignored: /node_modules/, aggregateTimeout: 300, poll: true } }); var hotMiddleware = webpackHotMiddleware(devCompiler, { log: false }); var server = express(); server.use(history()); server.use(devMiddleware); server.use(hotMiddleware); server.listen(3008, function(err) { if (err) throw new gutil.PluginError("webpack-dev-server", err); opn("http://localhost:3008") }); });
把以上相關(guān)的package寫入package.json并npm install
{ "dependencies": { "babel-runtime": "^6.26.0", "react": "^16.4.1" }, "devDependencies": { "autoprefixer": "^9.1.5", "babel-core": "^6.26.3", "babel-eslint": "^9.0.0", "babel-loader": "^7.1.5", "babel-plugin-external-helpers": "^6.22.0", "babel-plugin-import": "^1.9.1", "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators-legacy": "^1.3.5", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", "connect-history-api-fallback": "^1.5.0", "copy-webpack-plugin": "^4.5.2", "css-loader": "^1.0.0", "eslint": "^5.6.0", "eslint-loader": "^2.1.1", "eslint-plugin-react": "^7.11.1", "express": "^4.16.3", "file-loader": "^2.0.0", "gulp": "^3.9.1", "gulp-sequence": "^1.0.0", "gulp-util": "^3.0.8", "html-webpack-plugin": "^3.2.0", "http-proxy-middleware": "^0.18.0", "less": "^3.8.1", "less-loader": "^4.1.0", "node-sass": "^4.9.0", "opn": "^5.3.0", "path": "^0.12.7", "postcss": "^6.0.22", "postcss-loader": "^3.0.0", "react-hot-loader": "^4.3.4", "sass-loader": "^7.0.3", "style-loader": "^0.23.0", "url-loader": "^1.1.1", "webpack": "^4.12.0", "webpack-cli": "^3.1.0", "webpack-dev-middleware": "^3.1.3", "webpack-hot-middleware": "^2.22.3", "webpack-merge": "^4.1.4" } }
然后在根目錄創(chuàng)建index.html,內(nèi)容如下:
接著,編寫一個(gè)react組件
// 文件路徑:react-template/src/components/myFirstComponent/myFirstComponent.jsx import { hot } from "react-hot-loader"; // @hot 可以是react組件熱重載 @hot(module) class MyFirstComponent extends React.Component { state = { text: "Hello React" }; /** 組件生命周期鉤子函數(shù):在組件掛載完成后立即被調(diào)用 */ componentDidMount() { console.log("組件掛載完成!"); } render() { return ({this.state.text}, I am {this.props.author}!) } } export default MyFirstComponent;
// 文件路徑:react-template/src/index.js import MyFirstComponent from "./components/myFirstComponent/myFirstComponent" ReactDOM.render(, document.getElementById("app"));
最后,打開(kāi)CMD:
$ gulp dev
廢話少說(shuō),直接上圖:
瀏覽器會(huì)自動(dòng)打開(kāi):
你還可以試著修改組件的內(nèi)容,你會(huì)發(fā)現(xiàn)每當(dāng)你按下保存鍵,瀏覽器會(huì)跟著實(shí)時(shí)變化
好了,前面折騰了這么久,現(xiàn)在你可以去開(kāi)發(fā)你的react應(yīng)用了。只不過(guò)嘛,現(xiàn)在你能自由地開(kāi)發(fā)調(diào)試了,但是還不能構(gòu)建產(chǎn)品包,所以接下來(lái)我們還需要再配置一下 如何構(gòu)建生產(chǎn)環(huán)境的代碼。
webpack構(gòu)建生產(chǎn)環(huán)境代碼配置webpack.pro.js配置文件
var base = require("./webpack.base.js"), merge = require("webpack-merge"), HtmlWebpackPlugin = require("html-webpack-plugin"), BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin, WebpackMd5Hash = require("webpack-md5-hash"); module.exports = merge(base, { mode: "production", plugins: [ new WebpackMd5Hash(), new BundleAnalyzerPlugin(), new HtmlWebpackPlugin({ filename: "index.html", template: "index.html", chunks: ["main", "vendor"], inject: true, chunksSortMode: "auto", minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true } }) ] });
編寫gulp構(gòu)建生產(chǎn)環(huán)境代碼任務(wù):
var gulp = require("gulp"), gulpSequence = require("gulp-sequence"), gutil = require("gulp-util"), del = require("del"), uglify = require("gulp-uglify"), imagemin = require("gulp-imagemin"), express = require("express"), webpack = require("webpack"), webpackDevMiddleware = require("webpack-dev-middleware"), webpackHotMiddleware = require("webpack-hot-middleware"), history = require("connect-history-api-fallback"), opn = require("opn"); //...省略其他任務(wù) //清除 gulp.task("clean", function(cb) { del.sync("dist"); cb(); }); //圖片壓縮 gulp.task("copyImg", function() { return gulp .src("img/**/*.*") .pipe(imagemin()) .pipe(gulp.dest("dist/img/")); }); //復(fù)制無(wú)需編譯的js文件 gulp.task("copyJs", function() { return gulp .src([ "src/js_modules/react/pro/react.js", "src/js_modules/react-dom/pro/react-dom.js" ]) .pipe(uglify()) .pipe(gulp.dest("dist/js/")); }); //webpack production gulp.task("webpackPro", function(cb) { var webpackProConfig = require("./build/webpack.pro.js"); webpack(webpackProConfig, function(err, stats) { if (err) throw new gutil.PluginError("webpack:production", err); gutil.log( "[webpack:production]", stats.toString({ chunks: false, colors: true, timings: true, source: true, cachedAssets: false }) ); cb(); }); }); gulp.task("buildSuccess", function(cb) { gutil.log("[webpack:production]", "build success!"); cb(); }); gulp.task( "build", gulpSequence("clean", "copyImg", "copyJs", "webpackPro", "buildSuccess") );
最后,老規(guī)矩把相關(guān)的package寫入package.json并npm install
"dependencies": { "babel-runtime": "^6.26.0", "react": "^16.4.1" }, "devDependencies": { "autoprefixer": "^9.1.5", "babel-core": "^6.26.3", "babel-eslint": "^9.0.0", "babel-loader": "^7.1.5", "babel-plugin-external-helpers": "^6.22.0", "babel-plugin-import": "^1.9.1", "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators-legacy": "^1.3.5", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "babel-preset-react": "^6.24.1", "connect-history-api-fallback": "^1.5.0", "copy-webpack-plugin": "^4.5.2", "css-loader": "^1.0.0", "eslint": "^5.6.0", "eslint-loader": "^2.1.1", "eslint-plugin-react": "^7.11.1", "express": "^4.16.3", "file-loader": "^2.0.0", "gulp": "^3.9.1", "gulp-sequence": "^1.0.0", "gulp-util": "^3.0.8", "html-webpack-plugin": "^3.2.0", "http-proxy-middleware": "^0.18.0", "less": "^3.8.1", "less-loader": "^4.1.0", "node-sass": "^4.9.0", "opn": "^5.3.0", "path": "^0.12.7", "postcss": "^6.0.22", "postcss-loader": "^3.0.0", "react-hot-loader": "^4.3.4", "sass-loader": "^7.0.3", "style-loader": "^0.23.0", "url-loader": "^1.1.1", "webpack": "^4.12.0", "webpack-cli": "^3.1.0", "webpack-dev-middleware": "^3.1.3", "webpack-hot-middleware": "^2.22.3", "webpack-merge": "^4.1.4" }
最后的最后,命令行輸入gulp build試試效果吧!
附錄 babel-loader配置文件{ "presets": [ [ "env", { "modules": false, "targets": { "browsers": ["last 5 versions", "IE 9"] } } ], "react" ], "plugins": [ [ "transform-runtime", { "polyfill": false, "regenerator": true } ], "external-helpers", "syntax-dynamic-import", "transform-class-properties", "transform-decorators-legacy", [ "import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" } ], "react-hot-loader/babel" ], "env": { "test": { "presets": [ [ "env", { "modules": false, "targets": { "browsers": [ "last 5 versions", "IE 9" ] } } ], "react" ], "plugins": [ [ "transform-runtime", { "polyfill": false, "regenerator": true } ], "external-helpers", "syntax-dynamic-import", "transform-es2015-modules-commonjs", "transform-class-properties", "transform-decorators-legacy", [ "import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" } ] ] } } }eslint-loader配置文件
{ "root": true, "env": { "es6": true, "browser": true, "node": true }, "parser": "babel-eslint", "parserOptions": { "sourceType": "module", "ecmaFeatures": { "jsx": true, "experimentalObjectRestSpread": true } }, "globals": { "ReactDOM": false, "React": false, "jest": false, "test": false, "expect": false, "describe": false, "it": false }, "plugins": ["react"], "extends": ["eslint:recommended", "plugin:react/recommended"], "settings": { "react": { "version": "16.4.1" } }, "rules": { "no-extra-semi": 0, "no-console": 0, "react/prop-types": 0, "no-extra-boolean-cast": 0, "no-else-return": [1, { "allowElseIf": false }], "no-loop-func": 1, "arrow-spacing": 1, "eqeqeq": 2, "no-restricted-properties": [ 2, { "object": "disallowedObjectName", "property": "disallowedPropertyName" }, { "object": "disallowedObjectName", "property": "anotherDisallowedPropertyName", "message": "Please use allowedObjectName.allowedPropertyName." } ], "no-return-assign": [2, "always"], "no-sequences": 2, "no-throw-literal": 2, "no-unmodified-loop-condition": 2, "no-useless-return": 2, "prefer-promise-reject-errors": [2, {"allowEmptyReject": true}], "require-await": 2, "jsx-quotes": [2, "prefer-double"], "prefer-const": 2 } }postcss-loader配置文件
module.exports = { plugins:[ require("autoprefixer")({ browsers:[ "last 3 versions","iOS 7","not ie <= 9", "Android >= 4.0", "last 3 and_chr versions", "last 3 and_ff versions", "last 3 op_mob versions", "last 3 op_mob versions", "last 3 op_mini versions" ], //是否美化屬性值 cascade:true, //是否去掉不必要的前綴 remove:true }) ] };
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/98318.html
摘要:只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙只有動(dòng)手,你才能真正掌握一門技術(shù)持續(xù)更新中項(xiàng)目地址求求求源碼系列跟一起學(xué)如何寫函數(shù)庫(kù)中高級(jí)前端面試手寫代碼無(wú)敵秘籍如何用不到行代碼寫一款屬于自己的類庫(kù)原理講解實(shí)現(xiàn)一個(gè)對(duì)象遵循規(guī)范實(shí)戰(zhàn)手摸手,帶你用擼 Do it yourself!!! 只有動(dòng)手,你才能真的理解作者的構(gòu)思的巧妙 只有動(dòng)手,你才能真正掌握一門技術(shù) 持續(xù)更新中…… 項(xiàng)目地址 https...
摘要:從零開(kāi)始搭建同構(gòu)應(yīng)用二項(xiàng)目工程化瀏覽器端在從零開(kāi)始同構(gòu)開(kāi)發(fā)一中我們已經(jīng)能實(shí)現(xiàn)基本的配置和編譯了。接下來(lái)我們需要將編譯工作工程化。配置作用自動(dòng)生成自動(dòng)在引入,。文件內(nèi)容如下同構(gòu)開(kāi)發(fā)配置自動(dòng)刷新這里我們用到的修飾器特性。 從零開(kāi)始搭建React同構(gòu)應(yīng)用(二) 項(xiàng)目工程化(瀏覽器端) 在從零開(kāi)始React同構(gòu)開(kāi)發(fā)(一)中我們已經(jīng)能實(shí)現(xiàn)基本的React配置和編譯了。接下來(lái)我們需要將編譯工作工程...
摘要:從零開(kāi)始的新項(xiàng)目高級(jí)篇掘金承接上篇,本篇繼續(xù)講解一些更加進(jìn)階的內(nèi)容,包括列表綁定自定義屬性雙向綁定表達(dá)式鏈表達(dá)式動(dòng)畫注入測(cè)試等。 從零開(kāi)始的 Android 新項(xiàng)目 8 - Data Binding 高級(jí)篇 - 掘金 承接上篇,本篇繼續(xù)講解一些更加進(jìn)階的內(nèi)容,包括:列表綁定、自定義屬性、雙向綁定、表達(dá)式鏈、Lambda表達(dá)式、動(dòng)畫、Component注入(測(cè)試)等。 Demo源碼庫(kù):D...
摘要:寫在前面準(zhǔn)備學(xué)習(xí)一下和相關(guān)的東西,官方的腳手架看起來(lái)太繁瑣,所以打算自己來(lái)搭建一個(gè),參考了這個(gè)文檔從零搭建全家桶框架教程步驟上都差不多第一步,依賴總覽完成到我現(xiàn)在半成品的過(guò)程中,目前完成開(kāi)發(fā)模式的相關(guān)操作,添加了按需加載的地步。 寫在前面 準(zhǔn)備學(xué)習(xí)一下react和webpack相關(guān)的東西,官方的腳手架看起來(lái)太繁瑣,所以打算自己來(lái)搭建一個(gè),參考了這個(gè)文檔從零搭建React全家桶框架教程;...
摘要:從零開(kāi)始搭建同構(gòu)應(yīng)用三配置這篇文章來(lái)講解來(lái)配置,我們先從最簡(jiǎn)單的方法開(kāi)始,用的方式模擬實(shí)現(xiàn)。影響生產(chǎn)環(huán)境下執(zhí)行效率。最后權(quán)衡下,還是決定使用現(xiàn)在多一套編譯配置的方案。新建,寫入以下內(nèi)容以為例,注意不能少。 從零開(kāi)始搭建React同構(gòu)應(yīng)用(三):配置SSR 這篇文章來(lái)講解來(lái)配置server side render,我們先從最簡(jiǎn)單的方法開(kāi)始,用cli的方式模擬實(shí)現(xiàn)SSR。 demo在這里 ...
摘要:有沒(méi)有辦法實(shí)現(xiàn)就局部刷新呢當(dāng)然是有第十步執(zhí)行為了實(shí)現(xiàn)局部熱加載,我們需要添加插件。 前言 用了3個(gè)多月的vue自認(rèn)為已經(jīng)是一名合格的vue框架api搬運(yùn)工,對(duì)于vue的api使用到達(dá)了一定瓶頸,無(wú)奈水平有限,每每深入底層觀賞源碼時(shí)候都迷失了自己。 遂決定再找個(gè)框架學(xué)習(xí)學(xué)習(xí)看看能否突破思維局限,加上本人早已對(duì)React、RN技術(shù)垂涎已久,于是決定找找教程來(lái)學(xué)習(xí)。無(wú)奈第一步就卡在了環(huán)境搭...
閱讀 1907·2021-11-23 09:51
閱讀 1550·2021-11-19 09:40
閱讀 3223·2021-11-11 11:01
閱讀 1122·2021-09-27 13:34
閱讀 1854·2021-09-22 15:56
閱讀 2138·2019-08-30 15:52
閱讀 1074·2019-08-30 14:13
閱讀 3487·2019-08-30 14:10