真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

webpack4.0+vue2.0如何利用批處理生成前端單頁或多頁應(yīng)用

這篇文章將為大家詳細(xì)講解有關(guān)webpack4.0+vue2.0如何利用批處理生成前端單頁或多頁應(yīng)用,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)建站自2013年創(chuàng)立以來,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站制作、成都做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元海滄做網(wǎng)站,已為上家服務(wù),為海滄各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:13518219792

批處理

前端現(xiàn)在在做項(xiàng)目的時(shí)候大多數(shù)遇到的都是單頁面應(yīng)用,但有時(shí)需要做多頁面的時(shí)候,會(huì)把單頁拿過來修改成多頁面,如果代碼多了,對單頁或多頁的配置可能會(huì)混亂,那么有沒有更好的方式能把單頁面和多頁面不同的配置代碼分開,能更清楚的分辯他們的區(qū)別,這里是利用 批處理 對前端構(gòu)建進(jìn)行部署 git地址 目錄分為三塊

single //單頁代碼 
share // 共用代碼 
many //多頁代碼

只需要用到 批處理 對其中兩者進(jìn)行合并就能生成想要的單頁或多頁應(yīng)用,提示需要安裝國內(nèi)的 npm淘寶鏡像

如果未安裝的需要自行修改build.bat里的命令行 call cnpm installcall npm install

如下所示:

webpack4.0+vue2.0如何利用批處理生成前端單頁或多頁應(yīng)用

先選擇存放路徑,輸入項(xiàng)目名,選擇要生成的是單頁還是多頁

webpack4.0+vue2.0如何利用批處理生成前端單頁或多頁應(yīng)用

這里以單頁為示例,其實(shí)就是簡單的對文件進(jìn)行復(fù)制,復(fù)制完成后會(huì)自動(dòng)安裝依賴

webpack4.0+vue2.0如何利用批處理生成前端單頁或多頁應(yīng)用

安裝完依賴后還會(huì)自動(dòng)運(yùn)行項(xiàng)目 如上開啟的項(xiàng)目端口為8080

目錄如下

webpack4.0+vue2.0如何利用批處理生成前端單頁或多頁應(yīng)用

webpack4 共同配置(share)

這里用到了最新的webpack4.0,它簡化了很多配置,多線程輸出,更快的構(gòu)建能力,大大提高了開發(fā)的效率

首先看下配置文件 config.js

const path = require('path'),
 config = {
  //開發(fā)環(huán)境配置
  dev: {
   port: 8080,
   // 接口代理
   proxyTable: {
    '/v2': {
     target: 'https://api.douban.com',
     changeOrigin: true
    },
   },
  },
  //生產(chǎn)環(huán)境配置
  build: {
   packName: 'myProjcet', //項(xiàng)目打包后名稱
   outputPath: '', //打包后項(xiàng)目輸出路徑
   templatePath: 'template.html', //html模版路徑,基于根路徑下
   htmlShortPath: '/', //html文件輸出路徑, 基于outputPath
   resourcesPath: '', //最終打包路徑
   resourcesShortPath: 'resources', //資源目錄 {packName}/resources
  },
  switchVal: {
   to_rem: false, //是否開啟px轉(zhuǎn)rem
   to_eslint: false, //是否開啟eslint語法檢測
  },
 };

//輸出的目錄
config.build.outputPath = path.resolve(__dirname, '../../dist/', config.build.packName);
//最終輸出目錄項(xiàng)目存放路徑
config.build.resourcesPath = path.join(config.build.outputPath, config.build.resourcesShortPath);

module.exports = config;

這里有開發(fā)環(huán)境下的接口代理,

生產(chǎn)環(huán)境的目錄名稱和路徑

還有可選的是否轉(zhuǎn)換頁面字體為 remeslint 語法檢測

eslint 校驗(yàn)是默認(rèn)的規(guī)則校驗(yàn)

它還有其它的三種 通用規(guī)則

可根據(jù)自身喜好去設(shè)置

然后是 utils.js 工具方法

module.exports = {
 /***
  * 獲取src一級目錄
  */
 getFiles() {
  const files = glob.sync('src/**/'),
   arr = [];

  files.forEach((filepath) => {
   let name = filepath.split('/')[1];
   if (name) {
    arr.push(...[name]);
   }
  })

  let obj = {};
  if (arr.length) {
   [...new Set(arr)].map(item => {
    obj[`@${item}`] = path.join(__dirname, `../src/${item}`);
   })
  }

  return obj
 },
 /**
  * 多頁面命名 獲取每個(gè)多頁對應(yīng)的js名命名
  * **/
 getFileName() {
  let fileName = glob.sync('src/**/index.js');
  entryArr = {};
  fileName.forEach(function(path) {
   let arr = path.split('/');
   let name = arr[arr.length - 2];
   entryArr[name] = './' + path;
  })
  return entryArr;
 },
 /***
  * 靜態(tài)目錄存放路徑
  */
 assetsPath(_path) {
  return path.posix.join(config.build.resourcesShortPath, _path);
 },
 copyDir(source, target) {
  rm('-rf', target);
  mkdir('-p', target);
  cp('-R', source, target);
 }
}

再來看在開發(fā)和生產(chǎn)共用的代碼 webpack.base.conf.js

首先看下一些基本的對 vue、css、js 這些loader的操作

rules: [
    { test: /\.vue$/, loader: 'vue-loader', },
    { test: /\.css$/, use: ['style-loader', 'css-loader'] },
    { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
    { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
    {
     test: /\.js$/,
     loader: !process.env.NODE_ENV ? 'happypack/loader?id=happy-babel' : 'babel-loader',
     //loader: 'babel-loader',
     exclude: /(node_modules|lib)/,
     include: [ // 表示只解析以下目錄,減少loader處理范圍
      path.resolve(__dirname, '../src'),
     ],
    },
    {
     test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
     use: [{
      loader: 'file-loader',
      options: {
       //生產(chǎn)環(huán)境真實(shí)路徑
       name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
      }
     }]
    },
    {
     test: /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/,
     use: {
      loader: 'url-loader',
      options: {
       limit: 10000,
       //生產(chǎn)環(huán)境真實(shí)路徑
       name: utils.assetsPath('image/[name].[hash:7].[ext]')
      }
     }
    },
   ]

嗯都給了注釋,要注意的是 css、less、scss 的loader順序,不要寫反因?yàn)樗菑那巴筮@樣編譯的 如果找不到前面的后面的loader也就無法執(zhí)行 js 的loader用了一段這個(gè)

!process.env.NODE_ENV ? 'happypack/loader?id=happy-babel' : 'babel-loader',

因?yàn)樵谏a(chǎn)環(huán)境下打包時(shí) js loader的編譯會(huì)很慢,所以開啟了多線程去處理 js loader的編譯

HappyPack = require('happypack'),
 os = require('os'),
 happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length }),
 //利用多線程解決js loader編譯過程耗時(shí) 除scss無法使用 css、vue都可使用 (webpack4本來就是多線程)
 createHappyPlugin = (id, loaders) => new HappyPack({
  id: id,
  loaders: loaders,
  threadPool: happyThreadPool,
  verbose: true, //允許 HappyPack 輸出日志
 });

需要在 plugins 下加上下面這段

createHappyPlugin('happy-babel', [{
 loader: 'babel-loader',
 options: {
  babelrc: true,
  cacheDirectory: true // 啟用緩存
 }
}]),

happy-babel 就是找到上面loader的id,但因?yàn)閣ebpack4本來就是多線程的,這樣做可能多此一舉,暫時(shí)沒有測試過量大時(shí)編譯效果

還有這個(gè)

new VueLoaderPlugin()

vue-loader 版本為15.0以后都要加上

其它在升級到webpack4.0后還是有不少的坑,

就比如4之前可用的合并加載文件

new webpack.optimize.MinChunkSizePlugin({minChunkSize: 30000}),

這個(gè)已經(jīng)整合到 splitChunks 里面去了,再用的話就會(huì)沖突報(bào)錯(cuò)

因?yàn)橹皼]有留意 用3升4的過程中沒有刪除它,所以大家要重新配置4的時(shí)候還是重新一步步配置,否則很多報(bào)錯(cuò)都莫名其妙,接著往下看

if (!process.env.NODE_ENV) {
 for (let i = 1; i < 3; i++) {
  //使用mini-css-extract-plugin在生產(chǎn)環(huán)境要把style-loader覆蓋,它們會(huì)有沖突
  config.module.rules[i].use[0] = {
   loader: MiniCssExtractPlugin.loader,
  };
  //自動(dòng)添加樣式補(bǔ)全放
  config.module.rules[i].use.splice(2, 0, 'postcss-loader');
 }

 //css樣式合并
 config.plugins.push(
  new MiniCssExtractPlugin({
   filename: utils.assetsPath('css/[name].[chunkhash:8].css'),
  })
 )
}

生產(chǎn)環(huán)境下原來是用 ExtractTextPlugin 插件現(xiàn)在都改成了 MiniCssExtractPlugin

for循環(huán)里面主要是把 vue、css、less、scss 的第一個(gè)數(shù)組 style-loader 覆蓋成 MiniCssExtractPlugin 否則會(huì)有沖突,

自動(dòng)添加前綴的 postcss-loader 要放到最后面,這也是執(zhí)行順序的問題

在項(xiàng)目最外層要增加一個(gè) postcss.config.js 內(nèi)容是

module.exports = {
 plugins: [
  require('autoprefixer')({
   browsers: ['last 20 versions']
  })
 ]
}

require的是一個(gè)自動(dòng)補(bǔ)全css前綴的插件 last 20 versions 指的是兼容主流瀏覽器最近的20個(gè)版本,當(dāng)然如果想要兼容到某個(gè)瀏覽器的特定版本也可以這樣寫

'last 10 Chrome versions',
 'last 5 Firefox versions',
 'Safari >= 6', 
 'ie> 8

接下來是前面提過的 px轉(zhuǎn)remeslint 語法檢查,是否開啟和關(guān)閉是在 config.js 里設(shè)置

build.js 是這里生產(chǎn)打包,操作都是先清空原來的輸出目錄,復(fù)制靜態(tài)文件到輸出目錄 然后打包

const spinner = ora("開始構(gòu)建生產(chǎn)環(huán)境.....");
spinner.start();

//清空輸出目錄
rm("-rf", config.build.outputPath);

//復(fù)制static到輸出目錄
utils.copyDir("./static/*", config.build.resourcesPath);
webpack(webpackConfig).run((err, stats) => {
 spinner.stop();
 if (err) throw err;

 // 輸出編譯結(jié)果
 process.stdout.write(stats.toString({
  colors: true,
  modules: false,
  children: false,
  chunks: false,
  chunkModules: false,
  timings: false
 }) + "\n\n");
});

以上就是使用單頁或多頁共同的代碼塊

webpack4 單頁配置(single)

單頁應(yīng)用的目錄結(jié)構(gòu)主要是這樣的,和一般開發(fā)中的 vue 項(xiàng)目結(jié)構(gòu)一樣

build
 --views
  --index.html
  --404.html
 --build.js
 --config.js
 --dev-server.js
 --utils.js
 --webpack.base.conf.js
 --webpack.dev.conf.js
 --webpack.prod.conf.js
 src
 --conponents
 --css
 --font
 --images
 --mixins
 --pages //頁面目錄
 --router
 --store
 --App.vue
 --index.js
 static
 --jquery
 mode_modules

看build里的配置文件,前面講過了 build.js、config.js、utils.js、webpack.prod.conf.js 現(xiàn)在就先說下 webpack.dev.conf.js

const webpackConfig = merge(baseWebpackConfig, {
 mode: "development",
 entry: ["webpack-hot-middleware/client?noInfo=true&reload=true"].concat("./src/index.js"),
 devtool: "eval-source-map",
 output: {
  path: config.build.outputPath,
  filename: "index.js",
 },
 module: {
  rules: []
 },
 resolve: {},
 plugins: [
  new webpack.HotModuleReplacementPlugin(),
  new Jarvis({
   port: 1337
  })
 ],
 devServer: { inline: true },
});

webpack4.0新增了一個(gè) mode為development/production ,兩種模式在不同環(huán)境下都做了優(yōu)化操作,想要訪問這兩種模式還是需要用到

process.env.NODE_ENV

關(guān)于頁面熱加載直接使用webpack自帶的熱加載功能 HotModuleReplacementPlugin 然后和入口文件 src/index.js 做一個(gè)合并

["webpack-hot-middleware/client?noInfo=true&reload=true"].concat("./src/index.js")

后面的 noinforeload 是可配置的,如果想繼續(xù)增加參數(shù)可往這里添加, 傳送門

然后開啟熱加載 devServer: { inline: true }

output 里的path路徑我指向的是打包輸出路徑,webpack開發(fā)環(huán)境 是打包到內(nèi)存的并不是真的打包,filename是給了個(gè)固定的 index.js

這個(gè)是要寫到 html 里做為整個(gè)項(xiàng)目的入口,也就是說整個(gè)項(xiàng)目運(yùn)行就靠這個(gè) index.js ,

在plugins里有一個(gè) new Jarvis 這里的端口是1337,項(xiàng)目運(yùn)行后可以打開這個(gè)端口來看下文件大小,項(xiàng)目運(yùn)行是否出錯(cuò)等等, 這個(gè)可視化窗口功能還不錯(cuò),適合有雙屏的同學(xué)

接下來看下 webpack.prod.conf.js

const webpackConfig = {
 entry: { index: './src/index.js' }, //webpack4默認(rèn)會(huì)去查找./src/index.js
 output: {
  path: config.build.outputPath,
  publicPath: '/',
  filename: utils.assetsPath('js/[name].[chunkhash:8].js'),
  chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js')
 },
 mode: 'production',
 devtool: 'false',
 module: { rules: [] },
 optimization: {
  runtimeChunk: { //獲取頁面共同引用的代碼
   name: "manifest"
  },
  splitChunks: {
   chunks: 'initial',
   minChunks: 2,
   maxInitialRequests: 5,
   minSize: 30000, //
   maxInitialRequests: 3,
   automaticNameDelimiter: '~',
   cacheGroups: {
    vendors: {
     name: 'vendors',
     test: /[\\/]node_modules[\\/]/,
     priority: -10,
     enforce: true,
    },
    default: {
     test: /[\\/]src[\\/]/,
     priority: -20,
     reuseExistingChunk: true
    }
   }
  }
 },
 plugins: [
  new WebpackBar({
   minimal: false,
  }),
  new HtmlWebpackPlugin({
   filename: path.join(config.build.htmlShortPath, 'index.html'),
   template: config.build.templatePath,
   inject: true,
   chunks: ['manifest', 'index'], // 引入index.js
   minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: false
   }
  }),
  //css壓縮
  new OptimizeCssAssetsPlugin({
   assetNameRegExp: /\.css$/g,
   cssProcessor: require('cssnano'),
   cssProcessorOptions: { safe: true, discardComments: { removeAll: true } },
   canPrint: true
  }),
 ]
};

這里說下在output下的publicPath,如果要把打包后的文件指向一個(gè)相對路徑要加上 / 要不然生成出來的的入口文件會(huì)變成 resources/js/xxx.js 而不是我們期待的 /resources/js/xxx.js 再則圖片的路徑也會(huì)變成 resources/image/...png ,這樣是無效的路徑,當(dāng)然這還是要看你用的是相對路徑還是絕對路徑了

來看下 optimization 這個(gè)東西,這是webpack4新加的功能用于代碼的合并策略,這里是對兩個(gè)地方的js進(jìn)行合并一個(gè)是npm包一個(gè)是項(xiàng)目下的代碼

cacheGroups: {
 vendors: {
  name: 'vendors',
  test: /[\\/]node_modules[\\/]/,
  priority: -10,
  enforce: true,
 },
 default: {
  test: /[\\/]src[\\/]/,
  priority: -20,
  reuseExistingChunk: true
 }
}

這是符合合并規(guī)則條件的共同設(shè)置

chunks: 'initial',
minChunks: 2,
maxInitialRequests: 5,
minSize: 30000, //
maxInitialRequests: 3,
automaticNameDelimiter: '~',

也可以把他們拎到具體的合并對象下去做單獨(dú)的規(guī)則設(shè)置

然后在 plugins 下引用上面的合并后的js

new HtmlWebpackPlugin({
   filename: path.join(config.build.htmlShortPath, 'index.html'),
   template: config.build.templatePath,
   inject: true,
   chunks: ['manifest', 'index'], // 引入index.js
   minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: false
   }
  }),

chunks 它有如下三個(gè)模式,可自行調(diào)整

  • async表示只從異步加載得模塊(動(dòng)態(tài)加載import())里面進(jìn)行拆分

  • initial表示只從入口模塊進(jìn)行拆分

  • all表示以上兩者都包括

再看下 dev-server.js 啟動(dòng)項(xiàng)入口

let port = process.env.PORT || config.dev.port;
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.engine('html', ejs.__express);
app.set('view engine', 'html');
app.set('views', path.resolve(__dirname, 'views'));
app.use(compression()); //開啟gzip
//webpack編譯器
const compiler = webpack(webpackConfig);
//webpack-dev-server 中間件
const devMiddleware = require('webpack-dev-middleware')(compiler, {
 //這里必填 與webpack配置的路徑相同
 publicPath: webpackConfig.output.publicPath,
 stats: {
  colors: true,
  chunks: false,
 }
})
//熱更新中間件
const hotMiddleware = require('webpack-hot-middleware')(compiler);
//處理本地開發(fā)環(huán)境下的代理接口
Object.keys(config.dev.proxyTable).forEach(function(context) {
 const options = config.dev.proxyTable[context];
 if (typeof options === 'string') {
  options = {
   target: options
  }
 }
 if (~context.indexOf(',')) {
  context = context.split(',');
 }
 app.use(proxyMiddleware(context, options));
})
app.use(devMiddleware);
app.use(hotMiddleware);

// 靜態(tài)資源目錄 指向static目錄
app.use(express.static('./static'));

app.get('/*', function(req, res) {
 res.render('index');
});
//無路由時(shí)跳轉(zhuǎn)404
app.get('*', function(req, res) {
 res.render('404');
})
app.listen(port, function() {
 console.log('node啟動(dòng) 正在監(jiān)聽端口:', port)
})

這里利用 nodejs 調(diào)用模板進(jìn)行頁面渲染

app.set('views', path.resolve(__dirname, 'views'));

指向的是當(dāng)前 build 下的 views 目錄下的html文件,

開啟熱更新和開發(fā)接口代理

app.use(devMiddleware);
app.use(hotMiddleware);

app.use(express.static('./static')); 指向本地的靜態(tài)資源

比如本地的圖片路徑是 /images/jpge.jpg ,

在開發(fā)環(huán)境下訪問就會(huì)變成 http://localhost:8080/static/images/jpge.jpg ,

app.get('/*', function(req, res) {
 res.render('index');
});

把所有路徑直接指向到 views/index.html 下 文件內(nèi)容如下


 
 
     

index.js 就是之前的入口文件,必須要寫進(jìn)html文件里的,因?yàn)闆]有用 HtmlWebpackPlugin 做模板的映射,當(dāng)真正在開發(fā)環(huán)境下使用 (template.html) 模板是這樣子的


 
 
   

所以分了兩個(gè)模板去渲染頁面

webpack4 多頁配置(single)

多頁應(yīng)用的目錄結(jié)構(gòu)

build
 --views
  --index.html
  --404.html
 --build.js
 --config.js
 --dev-server.js
 --utils.js
 --webpack.base.conf.js
 --webpack.dev.conf.js
 --webpack.prod.conf.js
 src
 --conponents
 --css
 --font
 --images
 --mixins
 --pages //頁面目錄
 --new
  --index.js //入口
  --new.vue
 static
 --jquery
 mode_modules

build目錄下有三個(gè)文件有些改動(dòng)

dev-server.js 去掉了視圖目錄指向

因?yàn)槭嵌囗摰?,這里是獲取src目錄下的一級目錄做為路由

//這個(gè)獲取的是內(nèi)存路徑
app.get('/:viewname?', function(req, res, next) {
 var viewname = req.params.viewname ? req.params.viewname + '.html' : 'main.html';
 var filepath = path.join(compiler.outputPath, viewname);

 compiler.outputFileSystem.readFile(filepath, function(err, result) {
  if (err) {
   res.send('can\'t not find the file: ' + filepath).end;
   return;
  }
  res.set('content-type', 'text/html');
  res.send(result);
  res.end();
 });
});

然后是 webpack.dev.conf.js 里加了這一段

let entryObj = utils.getFileName();
Object.keys(entryObj).forEach((name) => {
 webpackConfig.entry[name] = ['webpack-hot-middleware/client?noInfo=true&reload=true'].concat(entryObj[name]);
 let plugin = new htmlWebpackPlugin({
  filename: name + '.html',
  template: config.build.templatePath,
  inject: true,
  chunks: [name]
 });
 webpackConfig.plugins.push(plugin);
})

獲取src目錄下的每個(gè)文件做為入口進(jìn)行模板渲染

同樣在 webpackprod.conf.js 也需要加上

let entryObj = utils.getFileName();
Object.keys(entryObj).forEach((name) => {
 webpackConfig.entry[name] = entryObj[name];
 let plugin = new HtmlWebpackPlugin({
  chunks: ['manifest', name],
  filename: name + '.html',
  template: config.build.templatePath,
  inject: true,
  environment: 'resources',
  minify: {
   removeComments: true,
   collapseWhitespace: true,
   removeAttributeQuotes: false
  }
 });
 webpackConfig.plugins.push(plugin);
})

這里多了一個(gè) environment 他是插入模板的一個(gè)變量,為區(qū)分開發(fā)和生產(chǎn)環(huán)境路徑


 
 
   

關(guān)于“webpack4.0+vue2.0如何利用批處理生成前端單頁或多頁應(yīng)用”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯(cuò),請把它分享出去讓更多的人看到。


分享名稱:webpack4.0+vue2.0如何利用批處理生成前端單頁或多頁應(yīng)用
標(biāo)題URL:http://weahome.cn/article/gssege.html

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部