最近項目所需,因此開始學習而且使用 APICloud 此款 hybrid APP 開發框架。粗略的看了下文檔和部分 Demo 後,已經對 APICloud 開發有必定基礎的瞭解。在這種過程令我有一點疑惑,APICloud 的開發流程和普通的 Web APP 開發實際上是很類似的,可是卻沒有對目前主流的構建工具備先關的教程。我發現雖然官方提供了一個 apicloud-polyfill 的功能,可是隻是爲了解決在項目中使用 ES6 的問題,並且整個 demo 的開發體驗並很差,每次修改代碼須要不停的構建在增量更新。隨着項目的複雜起來,以及對一些前端新特性的依賴,因此我打算本身動手弄一個適合 APICloud 使用的 Webpack 模板。javascript
APICloud 的開發模式其實就是之前的使用 jQuery 的 MPA 開發同樣,並且官方不推薦使用 SPA 的開發模式。css
|- dist |- lanuch |- src |- pages |- Foo |- index.js |- index.html |- image |- css |- scripts |- index.js |- index.html |- package.json |- config.xml |- webpack.config.json |- .babelrc |- .gitignore |- .syncignore |- index.html
上面是我我的對 APICloud 項目的文件夾分類。全部的源碼都存放在 src 文件夾內,Webpack 打包的主要目錄也是 src。html
這裏規定了每個單獨的 HTML 頁面都是須要一個 JavaScript 的入口文件,這也是爲了使用 Webpack 進行多頁面打包的基礎。前端
在設定好目錄結構以後,咱們須要開始編寫 Webpack 的 config 文件,配置相對來首都比較簡單,因此咱們就寫在一個文件內既可。vue
webpack.config.jsjava
const path = require('path') const webpack = require('webpack') const HtmlWebpackPlugin = require('html-webpack-plugin') const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin') const glob = require('glob') const paths = {} const configs = [] const setPath = (item, type) => { const dirname = path.dirname(item) if (paths[dirname]) { paths[dirname][type] = item } else { paths[dirname] = { [type]: item } } } glob.sync('./src/**/*.js', { ignore: './src/script/*.js' }).forEach(item => setPath(item, 'script')) glob.sync('./src/**/*.html').forEach(item => setPath(item, 'html')) Object.keys(paths).forEach(key => { const distName = key.replace('src', 'dist') configs.push({ entry: paths[key].script, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, distName) }, devtool: process.env.NODE_ENV === 'production' ? 'inline-source-map' : '#source-map', devServer: { host: '0.0.0.0', port: 8080, historyApiFallback: false, noInfo: true }, resolve: { extensions: ['.js', '.vue'], alias: { '@': path.resolve(__dirname, 'src'), 'vue$': 'vue/dist/vue.esm.js' } }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: 'babel-loader' }, { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader' ] }, { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader' ] } ] }, plugins: [].concat( [ new HtmlWebpackPlugin({ inlineSource: '.(js|css)$', template: paths[key].html }) ], process.env.NODE_ENV === 'production' ? [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"' } }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } }), new webpack.LoaderOptionsPlugin({ minimize: true }), new HtmlWebpackInlineSourcePlugin(), ] : [] ) }) }) module.exports = configs
package.jsonnode
{ "name": "webpack-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "cross-env NODE_ENV=production webpack --progress ", "dev": "cross-env NODE_ENV=development webpack-dev-server --open" }, "author": "", "license": "ISC", "devDependencies": { "babel-core": "^6.25.0", "babel-loader": "^7.1.1", "babel-preset-env": "^1.6.0", "cross-env": "^5.0.5", "css-loader": "^0.28.4", "file-loader": "^0.11.2", "glob": "^7.1.2", "html-webpack-inline-source-plugin": "0.0.9", "html-webpack-plugin": "^2.30.1", "style-loader": "^0.18.2", "webpack": "^3.5.4", "webpack-dev-server": "^2.7.1" }, "dependencies": { "vue": "^2.4.2" } }
在 Webpack 中咱們導出的是一個 config 數組,經過掃描 src 文件下的 JavaScript 和 HTML 文件,獲取它們的 path 信息,爲每個 JavaScript 進行打包。此外咱們可能還須要忽略一些 JavaScript 文件。webpack
在生產環境的構建下,我配置了將 css 和 JavaScript 都插入了 html 文件中,這又是官方的一種提倡作法。git
估計上面的配置好後,設置兩個 npm script 命令,方便開發使用:github
npm run dev
:啓動本地開發服務器;npm run build
:編譯項目,輸出到 dist 目錄下。在 APICloud 項目裏,咱們在根目錄有一個 index.html 文件,這是一個入口文件,咱們能夠經過修改 config.xml 來修改入口文件。通常來講都是經過 openFrame 或者 openWin 來嵌入或者打開一個頁面,在咱們的本地開發環境下,咱們經過 Webpack 啓動了一個本地服務器進行調試,因此咱們也須要將地址從目錄的相對地址改成一段 url。例如:
<script type="text/javascript"> apiready = function () { api.openFrame({ name: 'main', // url: 'dist/index.html', url: 'http://<你的本機 ip>:[端口號]', rect: { x: 0, y: 45, w: 'auto', h: 'auto' } }) } </script>
若是須要編譯項目的話,入口文件也須要修改爲相對路徑。這是一個麻煩的點,目前還沒什麼好辦法解決。
目標,在開發和編譯過程當中 Webpack 可以使用 eslint 檢查代碼,出現錯誤不經過,使用 aribnb 的 JavaScript 風格編程。
webpack.config.json
... configs.push({ ... module: { rules: [ { enforce: "pre", test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: "eslint-loader", }, ... ] } }) ...
package.json
{ ... devDependencies: { ... "eslint": "^4.4.1", "eslint-config-airbnb-base": "^11.3.1", "eslint-loader": "^1.9.0", "eslint-plugin-html": "^3.2.0", "eslint-plugin-import": "^2.7.0", ... } ... }
.eslintrc
{ "extends": "airbnb-base", "plugins": [ "html" ] }
.eslintignore
node_modules dist *.css
此次對 APICloud 集成 Webpack 嘗試,結果還算可。可是我的對 APICloud 的開發仍是很是的不滿意的,對於 React Native 來講:沒有熱更新、在 APP loader 下調試不能使用 Chrome developer tool等。看網上對這個框架的評價,也是處於一個較低的水平。只能經過此次項目的開發再深刻了解的它們的利弊了。