想一想也已經作過很多架構的項目了,有基於vue,基於react,基於thinkPHP,基於laravel的。css
作多了,也就對現有的架構有各類想法,有好的,有壞的,總之,用起來仍是不爽。vue-cli雖然能夠很快地構建並使用,尤爲是vue-cli v3.0,把webpack都封進@vue/cli
的sdk裏了,用起來更加乾淨、簡潔。html
可是,對於愛折騰的咱們,好吧,開個玩笑。重來,可是,對於頁面的優化,還有項目的架構,咱們不得不作多多少少的修改。前端
好了,介紹完畢,接下來,我就從零開始,一步一步建起先後端徹底分離的前端架構了。vue
因爲要介紹的不少,全寫在一篇裏,有些太長了。node
因此,我會分爲:react
建立開發環境下的webpack配置文件webpack
配置eslint、babel、postcsslaravel
建立項目文件、目錄架構git
經過koa實現本地數據接口模擬github
建立發佈環境下的webpack配置文件
建立測試環境下的webpack配置文件、以及測試用例 (TODO)
自動初始化構建項目(TODO)
這七篇來分別介紹。
建立項目文件夾 咱們就叫vue-construct
吧
初始化git git init
初始化npm npm init
建立項目文件 爲了能讓webpack跑起來,而不是一口氣只講配置而不運行一下,那樣未免有些空洞,因此咱們先建立一點項目文件和目錄。 在這以前咱們先安裝兩個包:vue、vue-router, npm i -S vue vue-router
。 咱們將項目代碼相關文件都放在名爲app
的文件夾下。我先都建立完,而後一個個介紹。
├── app
│ ├── app.vue
│ ├── common
│ │ ├── img
│ │ ├── js
│ │ └── scss
│ ├── index.html
│ ├── index.js
│ ├── router
│ │ └── index.js
│ └── views
│ └── home
│ └── index.vue
├── .gitignore
├── package-lock.json
├── package.json
└── webpack.config.js
複製代碼
node_modules的話就忽略了。
文件/文件夾 | 用途 |
---|---|
app.vue | 做爲vue的主文件 |
common | 裏面放公共的代碼 |
index.html | 頁面模板文件 |
index.js | 項目主入口文件 |
router | 放vue對應的router文件 |
views | 放視圖文件 |
.gitignore | 忽略node_module |
我們暫且不關係這些文件裏的具體代碼是什麼,等webpack配置完再說。
webpack
webpack-dev-server
複製代碼
爲了處理vue單頁文件,安裝:
vue-loader
複製代碼
爲了處理scss文件並從js中抽離,安裝:
node-sass
style-loader
css-loader
sass-loader
vue-style-loader
postcss
postcss-loader
autoprefixer
extract-text-webpack-plugin
複製代碼
爲了處理圖片和字體文件,安裝:
file-loader
url-loader
複製代碼
爲了支持高級語法-babel,安裝:
babel
babel-loader
babel-plugin-syntax-dynamic-import
babel-plugin-transform-object-rest-spread
babel-polyfill
babel-preset-env
複製代碼
爲了驗證代碼格式-eslint,安裝:
eslint
eslint-loader
eslint-plugin-html
babel-eslint
複製代碼
const webpack = require('webpack') const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') // 爲了抽離出兩份CSS,建立兩份ExtractTextPlugin // base做爲基礎的css,基本不變,因此,能夠抽離出來充分利用瀏覽器緩存 // app做爲迭代的css,會常常改變 const isProduction = process.env.NODE_ENV === 'production' const ExtractTextPlugin = require('extract-text-webpack-plugin') const extractBaseCSS = new ExtractTextPlugin( { filename:'static/css/base.[chunkhash:8].css', allChunks: true, disable: !isProduction // 開發環境下不抽離css } ) const extractAppCSS = new ExtractTextPlugin( { filename:'static/css/app.[chunkhash:8].css', allChunks: true, disable: !isProduction // 開發環境下不抽離css } ) // 減小路徑書寫 function resolve(dir) { return path.join(__dirname, dir) } // 網站圖標配置 const favicon = resolve('favicon.ico') // __dirname: 老是返回被執行的 js 所在文件夾的絕對路徑 // __filename: 老是返回被執行的 js 的絕對路徑 // process.cwd(): 老是返回運行 node 命令時所在的文件夾的絕對路徑 const config = { // sourcemap 模式 devtool: 'cheap-module-eval-source-map', // 入口 entry: { app: resolve('app/index.js') }, // 輸出 output: { path: resolve('dev'), filename: 'index.bundle.js' }, resolve: { // 擴展名,好比import 'app.vue',擴展後只須要寫成import 'app'就能夠了 extensions: ['.js', '.vue', '.scss', '.css'], // 取路徑別名,方便在業務代碼中import alias: { api: resolve('app/api/'), common: resolve('app/common/'), views: resolve('app/views/'), components: resolve('app/components/'), componentsBase: resolve('app/componentsBase/'), directives: resolve('app/directives/'), filters: resolve('app/filters/'), mixins: resolve('app/mixins/') } }, // loaders處理 module: { rules: [ { test: /\.js$/, include: [resolve('app')], loader: [ 'babel-loader', 'eslint-loader' ] }, { test: /\.vue$/, exclude: /node_modules/, loader: 'vue-loader', options: { extractCSS: true, loaders: { scss: extractAppCSS.extract({ fallback: 'vue-style-loader', use: [ { loader: 'css-loader', options: { sourceMap: true } }, { loader: 'postcss-loader', options: { sourceMap: true } }, { loader: 'sass-loader', options: { sourceMap: true } } ] }) } } }, { test: /\.(css|scss)$/, use: extractBaseCSS.extract({ fallback: 'style-loader', use: [ { loader: 'css-loader', options: { sourceMap: true } }, { loader: 'postcss-loader', options: { sourceMap: true } }, { loader: 'sass-loader', options: { sourceMap: true } } ] }) }, { test: /\.(png|jpe?g|gif|svg|ico)(\?.*)?$/, loader: 'url-loader', options: { limit: 8192, name: isProduction ? 'static/img/[name].[hash:8].[ext]' : 'static/img/[name].[ext]' } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 8192, name: isProduction ? 'static/font/[name].[hash:8].[ext]' : 'static/font/[name].[ext]' } } ] }, plugins: [ // html 模板插件 new HtmlWebpackPlugin({ favicon, filename: 'index.html', template: resolve('app/index.html') }), // 抽離出css extractBaseCSS, extractAppCSS, // 熱替換插件 new webpack.HotModuleReplacementPlugin(), // 更友好地輸出錯誤信息 new FriendlyErrorsPlugin() ], devServer: { proxy: { // 凡是 `/api` 開頭的 http 請求,都會被代理到 localhost:7777 上,由 koa 提供 mock 數據。 // koa 代碼在 ./mock 目錄中,啓動命令爲 npm run mock。 '/api': { target: 'http://localhost:7777', // 若是說聯調了,將地址換成後端環境的地址就哦了 secure: false } }, host: '0.0.0.0', port: '9999', disableHostCheck: true, // 爲了手機能夠訪問 contentBase: resolve('dev'), // 本地服務器所加載的頁面所在的目錄 // historyApiFallback: true, // 爲了SPA應用服務 inline: true, //實時刷新 hot: true // 使用熱加載插件 HotModuleReplacementPlugin } } module.exports = { config: config, extractBaseCSS: extractBaseCSS, extractAppCSS: extractAppCSS } 複製代碼
這一篇主要就作了三件事:
下一篇咱們將配置eslint、babel、postcss - 從零開始作Vue前端架構(2)