一個vue-cli建立專案webpack相關都配置合簡介

freeshine發表於2019-03-02

專案建立

# git clone project
git clone https://github.com/freeshineit/vue2_config.git

# install dependencies
cd vue2_config && npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build
複製程式碼

vue專案配置簡介

config 資料夾下的配置檔案

config/dev.env.js

module.exports = merge(prodEnv, {
  NODE_ENV: `"development"` // node環境為開發環境
})
複製程式碼

config/dev.env.js

config/prod.env.js

module.exports = {
  NODE_ENV: `"production"`  // node環境為生產環境
}
複製程式碼

config/prod.env.js

config/index.js

development

  dev: { //開發環境配置項
    assetsSubDirectory: `static`, // 虛擬靜態資源地址
    assetsPublicPath: `/`, 
    proxyTable: {}, // 伺服器代理
    // Various Dev Server settings
    host: `localhost`, // can be overwritten by process.env.HOST
    port: 8080, // 本地伺服器開啟的埠。如果被佔用,則會自動開啟一個端
    autoOpenBrowser: false, // 服務開啟是否自動開啟瀏覽器
    errorOverlay: true, // 是否錯誤疊加
    notifyOnErrors: true, // 是否通知錯誤
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
    useEslint: true, // 是否開啟eslint程式碼檢查
    // if 值為true,eslint顯示錯誤和警告的錯誤也將被覆蓋
    // 在瀏覽器中.
    showEslintErrorsInOverlay: false, 
    //...
  }
複製程式碼

production

  build: { // 生產環境配置項
    index: path.resolve(__dirname, `../dist/index.html`),  // 打包生成模版
    assetsRoot: path.resolve(__dirname, `../dist`), // 打包根路徑
    assetsSubDirectory: `static`, // 打包靜態資源地址 
    assetsPublicPath: `/`, // 公共路徑
    // 能夠提供將壓縮檔案恢復到原始檔原始位置的對映程式碼的方式,這意味著你可以在優化壓縮程式碼後輕鬆的進行除錯
    productionSourceMap: true, // sourcemap
    // ...
  }
複製程式碼

config/index.js

build 檔案下的配置檔案

build/build.js

// 移除已經編譯的檔案
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
  if (err) throw err
  // 當移除檔案成功,執行回撥時重新打包專案
  webpack(webpackConfig, (err, stats) => {
    spinner.stop() // 停止ora 的loading
    if (err) throw err // 出錯 丟擲錯誤
    // 在編譯完成的回撥函式中,在終端輸出編譯的檔案
    process.stdout.write(stats.toString({
      colors: true,
      modules: false,
      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
      chunks: false,
      chunkModules: false
    }) + `

`)
    if (stats.hasErrors()) { // build 失敗
      console.log(chalk.red(`  Build failed with errors.
`)) 
      process.exit(1) // 程式退出
    }
    console.log(chalk.cyan(`  Build complete.
`)) // build 完成 
    console.log(chalk.yellow(
      `  Tip: built files are meant to be served over an HTTP server.
` +
      `  Opening index.html over file:// won`t work.
`
    )) // 在終端中輸出提醒文案
  })
})
複製程式碼

build/build.js

build/utils.js

//根據`_path`生成資源路徑和檔案
exports.assetsPath = function (_path) { 
  const assetsSubDirectory = process.env.NODE_ENV === `production`
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory

  return path.posix.join(assetsSubDirectory, _path)
}
//...

// https://vue-loader.vuejs.org/en/configurations/extract-css.html
// 要使用動態樣式語言,你可下載下面幾種less、sass、stylus
// 例如安裝less執行: npm i -S less less-loader
// 就可以使用less了
return { 
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders(`less`),
sass: generateLoaders(`sass`, { indentedSyntax: true }),
scss: generateLoaders(`sass`),
stylus: generateLoaders(`stylus`),
styl: generateLoaders(`stylus`)
}
//...
複製程式碼

build/utils.js

build/vue-loader.conf.js

// 是vue-loader的一些配置項
module.exports = {
  // 呼叫utils工具類生成樣式loader的配置
  loaders: utils.cssLoaders({
    sourceMap: sourceMapEnabled,
    extract: isProduction
  }),
  // ...
}
複製程式碼

build/vue-loader.conf.js

build/webpack.base.conf.js

module.exports = {
  context: path.resolve(__dirname, `../`),
  entry: { // 入口檔案
    app: `./src/main.js`
  },
  output: { // 編譯輸出檔案
    path: config.build.assetsRoot, //匯出目錄的絕對路徑
    filename: `[name].js`, //匯出檔案的檔名
    publicPath: process.env.NODE_ENV === `production`
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath //生產模式或開發模式下html、js等檔案內部引用的公共路徑
  },
  resolve: {
    extensions: [`.js`, `.vue`, `.json`], //自動解析確定的擴充名,使匯入模組時可以不帶擴充名
    alias: { // 建立import或require的別名 方便簡寫匯入路徑
      `vue$`: `vue/dist/vue.esm.js`,
      `@`: resolve(`src`),
    }
  }
  //...
}
複製程式碼

build/webpack.base.conf.js

build/webpack.dev.conf.js

const devWebpackConfig = merge(baseWebpackConfig, {
    // ...
  plugins: [ // 外掛配置
    new webpack.DefinePlugin({ // webpack 自帶的外掛
      `process.env`: require(`../config/dev.env`)
    }),
    new webpack.HotModuleReplacementPlugin(), // webpack 自帶的外掛
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. // webpack 自帶的外掛
    new webpack.NoEmitOnErrorsPlugin(), // webpack 自帶的外掛
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({ // html模版處理配置
      filename: `index.html`, // 生成檔案
      template: `index.html`, // 模版檔案
      inject: true //注入的js檔案將會被放在body標籤中,當值為`head`時,將被放在head標籤中
    }),
    // copy custom static assets
    new CopyWebpackPlugin([ // 複製外掛 , 只要時複製static資料夾中檔案到config.dev.assetsSubDirectory資料夾下
      {
        from: path.resolve(__dirname, `../static`),
        to: config.dev.assetsSubDirectory,
        ignore: [`.*`] //忽視.*檔案
      }
    ])
  ],
  // ...
})
複製程式碼

build/webpack.dev.conf.js

build/webpack.prod.conf.js

const webpackConfig = merge(baseWebpackConfig, {
    // ...
  output: { // 生成環境 編譯輸出檔案
    path: config.build.assetsRoot, // 匯出檔案目錄
    filename: utils.assetsPath(`js/[name].[chunkhash].js`), //匯出js檔名,檔名帶有chunkhash碼
    chunkFilename: utils.assetsPath(`js/[id].[chunkhash].js`) // 非入口檔案的檔名,而又需要被打包出來的檔案命名配置,如按需載入的模組
  },
  plugins: [ // webpack 外掛配置
    new webpack.DefinePlugin({
      `process.env`: env  //配置全域性環境為生產環境
    }),
    new UglifyJsPlugin({ // js程式碼壓縮外掛
      uglifyOptions: {
        compress: { // 程式碼壓縮配置
          warnings: false  // 是否顯示警告, false 不顯示
        }
      },
      sourceMap: config.build.productionSourceMap,  // 是否生產sourcemap檔案
      parallel: true  // 並行
    }),
    new ExtractTextPlugin({ // 抽取css 樣式表 單獨打包
      filename: utils.assetsPath(`css/[name].[contenthash].css`), // 匯出css檔名,檔名帶有contenthash碼
      //設定下面選項為`false`不會從程式碼分割塊中提取CSS。
      //他們的CSS將被插入style-loader時,程式碼分割塊通過webpack已載入
      //它的當前設定為`true`, 因為我們看到sourcemaps都包括在程式碼分割bundle, 以及當它的`假`增加檔案大小
      // https://github.com/vuejs-templates/webpack/issues/1110
      allChunks: true,  // 所有塊
    }),
    // 壓縮提取的CSS。我們正在使用這個外掛,使之成為可能
    // 重複的CSS從不同的元件可以被刪除(deduped)
    new OptimizeCSSPlugin({  // 壓縮抽取到css
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { safe: true }
    }),
    // 生成在 `dist` 檔案下 `index.html`
    // 你可以通過編輯/ index.html自定義輸出(自定義模版中到內容)
    new HtmlWebpackPlugin({
      filename: config.build.index,  // 生成到檔名
      template: `index.html`, // 模版(當模版不存在時,生產檔案時雖然生成了,但是有點問題)
      inject: true, //注入的js檔案將會被放在body標籤中,當值為`head`時,將被放在head標籤中
      minify: { // html壓縮配置
        removeComments: true, //移除html中的註釋
        collapseWhitespace: true, // 移除html中的空格
        removeAttributeQuotes: true //移除html元素中屬性的引號
      },
      chunksSortMode: `dependency` // 按照依賴的順序引入
    }),
    new webpack.HashedModuleIdsPlugin(),
    new webpack.optimize.ModuleConcatenationPlugin(),
    // 分離公共js到vendor檔案中去
    new webpack.optimize.CommonsChunkPlugin({
      name: `vendor`, // 檔名
      minChunks (module) { //宣告公共的模組來自node_modules資料夾
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, `../node_modules`)
          ) === 0
        )
      }
    }),
    // 執行時模組提取webpack表現為了自己的檔案以防止每當應用程式包更新vendor檔案雜湊被更新
    // 下面主要是將執行時程式碼提取到單獨的manifest檔案中,防止其影響vendor.js
    new webpack.optimize.CommonsChunkPlugin({
      name: `manifest`,
      minChunks: Infinity
    }),
    // 本例項程式碼分塊,將它們捆在一個單獨的塊中提取共享塊,類似於vendor檔案的塊
    new webpack.optimize.CommonsChunkPlugin({
      name: `app`,
      async: `vendor-async`,
      children: true,
      minChunks: 3
    }),
    // 複製指定檔案靜態資源, 下面將static檔案內的複製靜態資源內容複製到指定資料夾
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, `../static`),
        to: config.build.assetsSubDirectory,
        ignore: [`.*`]
      }
    ])
  ]
})
複製程式碼

build/webpack.prod.conf.js

小結

使用vue-cli 腳手架建立,其實很簡單的,主要是和後臺合作,專案整合在一起。開發者瞭解webpack的相關配置非常有利於專案構建。如果搞不懂的話,自己可以去嘗試修改配置檢視效果。

相關文章