• webpack打包


    webpack打包:

    在使用webpack打包react项目,每次需要手动编译比较慢,webpack提供了一种热加载的方式,每次变化时自动编译及刷新页面,提升开发效率。同时,在本地开发时使用webpack服务器做代理,做接口mock数据的转发。
    1、首先安装webpack相关包:配置package.json文件,使用npm install 安装需要的包
    package.json文件

    {
      "name": "cl_html",
      "description": "",
      "main": "index.js",
      "dependencies": {
        "babelify": "^6.3.0",
        "react": "^0.14.8",
        "react-dom": "^0.14.8",
        "react-hot-loader": "^1.3.0",
        "watchify": "^3.4.0"
      },
      "scripts": {
        "start": "webpack-dev-server",
        "build": "webpack",
        "dev": "webpack-dev-server --devtool eval --progress --colors --content-base build"
      },
      "devDependencies": {
        "babel-core": "^6.17.0",
        "babel-loader": "^6.2.5",
        "babel-preset-es2015": "^6.16.0",
        "babel-preset-react": "^6.16.0",
        "browser-sync": "^2.11.1",
        "css-loader": "^0.25.0",
        "file-loader": "^0.9.0",
        "gulp": "^3.9.1",
        "gulp-if": "^2.0.1",
        "gulp-minify-html": "^1.0.6",
        "gulp-processhtml": "^1.1.0",
        "gulp-replace": "^0.5.4",
        "gulp-rev": "^7.0.0",
        "gulp-rev-collector": "^1.0.3",
        "gulp-rev-replace": "^0.4.3",
        "html-webpack-plugin": "^2.30.1",
        "react-hot-loader": "^1.3.0",
        "run-sequence": "^1.2.1",
        "style-loader": "^0.13.1",
        "url-loader": "^0.5.7",
        "webpack": "^1.13.2",
        "webpack-dev-server": "^1.16.2",
        "yargs": "^4.7.1",
         "html-webpack-plugin": "^2.30.1"
      }
    }
    View Code

    2、webpack.config.js配置文件:

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
    const webpack = require("webpack"); //访问内置的插件
    
    module.exports = {  // 主要有entry,output、module、plugins等配置项
       //target:"web",   //服务器和浏览器代码都可以用 JavaScript 编写,所以 webpack 提供了多种构建目标(target),你可以在你的 webpack 配置中设置。 默认是web 也可以设置为node
    
       //1、入口配置
       //单个入口的写法
       //entry: path.resolve(__dirname, 'js/app.js'),   //简单配置写法
       // entry:{
       //    main:path.resolve(__dirname, 'js/app.js'),
       // },
       //向 entry 属性传入「文件路径(file path)数组」将创建“多个主入口(multi-main entry)”
       // entry:  ['webpack/hot/dev-server', path.resolve(__dirname, 'js/app.js')],
    
       //非单页
       /*entry:{
          index:path.resolve(__dirname, 'js/app.js'),   //pageOne、pageTwo作为打包后的filename
          pageTwo:path.resolve(__dirname, 'js/app2.js')
       },*/
      /* entry:{
          pageOne:path.resolve(__dirname, 'js/app1.js'),
          pageTwo:path.resolve(__dirname, 'js/app2.js'),
          pageThree:path.resolve(__dirname, 'js/app3.js'),
       },*/
      entry: {
        index: [
          'webpack-dev-server/client?http://localhost:8099',
          'webpack/hot/only-dev-server',
          './js/index.js'
        ],
        common:['react','react-dom']
      },
      //2 、定义打包后的文件输出 单个入口的打包输出
      /*output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'index.min.js'
      },*/
      //多入口的打包
       output:{
          path: path.resolve(__dirname, 'build'),
          publicPath: "http://localhost:8099/build/",
          // filename:'[name].min.js',
          filename: '[name].[hash:6].js',
      },
    
      //使用CDN和hash
      /*  output: {
            path: "/home/proj/cdn/assets/[hash]",
            publicPath: "http://cdn.example.com/assets/[hash]/"
        },*/
    
      //loader 让 webpack 能够去处理那些非 JavaScript 文件
      module: {
        loaders: [  //在 webpack 的配置中 loader 有两个目标。
    
    // 1、识别出应该被对应的 loader 进行转换的那些文件。(使用 test 属性)
    // 2、转换这些文件,从而使其能够被添加到依赖图中(并且最终添加到 bundle 中)(use 属性)
        {
          test: /.jsx?$/,
          exclude: /node_modules/, //include exclude 添加必须处理的文件夹或屏蔽不需处理的文件夹
          loader: 'babel', //loader的名称  babel的配置项放在babelrc文件里面
          query: {
            presets: ['es2015','react']
          }
        },
        {
          test: /.css$/,
          loader: 'style!css'
        },
        {
          test: /.(png|jpg|gif)$/,
          loader: 'url-loader?limit=8192' // 这里的 limit=8192 表示用 base64 编码 <= 8K 的图像
        },
        // {
        //   test: /.js?$/,
        //   loaders: ['react-hot', 'babel'],
        //   include: [path.join(__dirname, 'js')]
        // }
        ]
      },
      //生成source maps 便于调试
        //配置生成Source Maps,选择合适的选项 source-map、cheap-module-source-map、eval-source-map、cheap-module-eval-source-map
        devtool: 'eval-source-map',
    
    //自动刷新配置(1)以命令行方式启动,配置devServer (2)以node 方式启动一个服务
        //命令行启动时 本地服务器  让浏览器检测代码的变化,自动刷新
      /*  devServer: {
            // contentBase: "./public",//本地服务器所加载的页面所在的目录,默认为根目录
            port: 8088,
            colors: true, //终端中输出结果为彩色
            historyApiFallback: true, //不跳转
            inline: true, //实时刷新
            hot: true //自动刷新
        },*/
      plugins: [
        //版权声明插件:在打包后的文件里添加版权声明
        new webpack.BannerPlugin("Copyright PAS Frontend."),
    
        // 设置生产环境全局变量,以便告诉所有类库,过滤不必要的代码
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': "production"
            }
        }),
    
        // 压缩代码,去掉评论注释等  减少文件体积
         new webpack.optimize.UglifyJsPlugin({
             output: {
              comments: false,
            },
            compress: {
              warnings: false
            }
         }),  //压缩
         //每次打包后index.html中的路径也会自动加上hash值
         new HtmlWebpackPlugin({
          template: path.resolve(__dirname, './index.html'),
          filename:path.resolve(__dirname, './index.build.html'),  //js路径替换成带hash的
           hash:true,
           title:"标题"
        }),
    
            // 拆分插件: 打包成不同文件
            new webpack.optimize.CommonsChunkPlugin({
                name: 'common', // 上面入口定义的节点组
                filename: 'build-common.js' //最后生成的文件名
            }),
    
    
            //热加载插件HMR
            // new webpack.HotModuleReplacementPlugin(),
          new webpack.HotModuleReplacementPlugin(),
          // new webpack.NoErrorsPlugin()
      ]
    }
    View Code

    (1)entry配置项:
    //单个入口的写法
    entry: path.resolve(__dirname, 'js/app.js'), //简单配置写法
    //对象形式传入,配置多个入口文件

    entry:{
    index:path.resolve(__dirname, 'js/app.js'), //index、pageTwo作为output打包后的filename
    pageTwo:path.resolve(__dirname, 'js/app2.js')
    }
    //向 entry 属性传入「文件路径(file path)数组」将创建“多个主入口(multi-main entry)”
    // entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'js/app.js')],


    (2)多入口的打包的输出配置,如果需要,filename可以配置参数,加上hash。
    publicPath来指定编译后的包(bundle)的访问位置。另外,打包后的文件加上随机字符串后,在index.html中引入的脚本路径也需要动态调整,这个publicPath会作为脚本的根路径

    output:{
    publicPath: "http://localhost:8099/build/",
    path: path.resolve(__dirname, 'build'),
    filename: '[name].[hash:6].js', //name就是entry中配置的键名,hash用于指定生成随机6为随机字符
    }


    (3)module 主要处理一些es6编译、css预处理、图片处理等
    //使用loaders对模块进行各种处理,如将es7es6转成es5

    module: {
    loaders: [{
    test: /.jsx?$/, //匹配要处理文件的扩展名 (必选)
    exclude: /node_modules/, //include exclude 添加必须处理的文件夹或屏蔽不需处理的文件夹
    loader: 'babel', //loader的名称 babel的配置项放在babelrc文件里面
    // query: { //为loader提供额外的设置选项。 //babel配置选项可以写在.babelrc文件中
    // presets: ['es2015','react'] //es2015 解析es6、 react 解析react中的jsx
    // }
    },
    {
    test: /.css$/,
    // loader: 'style!css' //style-loader css-loader
    /* loader: 'style!css?modules' //css module*/
    loader: 'style!css?modules!postcss'
    },
    {
    test: /.(png|jpg|gif)$/,
    loader: 'url-loader?limit=8192' // 这里的 limit=8192 表示用 base64 编码 <= 8K 的图像
    },
    //json文件处理
    {
    test: /.json$/,
    loader: "json"
    }
    ]
    },

    (4)plugins:webpack插件,压缩、热加载、拆分打包等,有些插件是webpack自带的可以直接使用,如BannerPlugin、UglifyJsPlugin等,但有些如HtmlWebpackPlugin需要自己安装 (npm install html-webpack-plugin --save-dev)

    plugins: [
    //版权声明插件:在打包后的文件里添加版权声明
    new webpack.BannerPlugin("Copyright PAS Frontend."),
    
    // 设置生产环境全局变量,以便告诉所有类库,过滤不必要的代码
    new webpack.DefinePlugin({
    'process.env': {
    'NODE_ENV': "production"
    }
    }),
    
    // 压缩代码,去掉评论注释等 减少文件体积
    new webpack.optimize.UglifyJsPlugin({
    output: {
    comments: false,
    },
    compress: {
    warnings: false
    }
    }), //压缩
    //每次打包后index.html中的路径也会自动加上hash值
    new HtmlWebpackPlugin({
    template: path.resolve(__dirname, './index.html'),
    filename:path.resolve(__dirname, './index.build.html'), //js路径替换成带hash的
    hash:true,
    title:"标题"
    }),
    
    // 拆分插件: 打包成不同文件
    new webpack.optimize.CommonsChunkPlugin({
    name: 'common', // 上面入口定义的节点组
    filename: 'build-common.js' //最后生成的文件名
    }),
    
    
    //热加载插件HMR
    // new webpack.HotModuleReplacementPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    // new webpack.NoErrorsPlugin()
    ]


    3、热加载 webpack-dev-server
    webpack-dev-server是一个小型的Node.js Express服务器,它使用webpack-dev-middleware来服务于webpack的包,除此自外,它还有一个通过Sock.js来连接到服务器的微型运行时.
    安装使用 npm install webpack-dev-server

    (1)启动一个webpack-server服务,使用该服务访问项目文件,如http://localhost:8099/index.html,后续再修改脚本时,不需要手动执行webpack打包,webpack-server会自动监听变化并刷新页面。

    webpack.server.js文件,使用node webpack.server.js启动服务
    var webpack = require('webpack');
    var WebpackDevServer = require('webpack-dev-server');
    var config = require('./webpack.config');
    
    new WebpackDevServer(webpack(config), {
    publicPath: config.output.publicPath,
    hot: true,
    historyApiFallback: false,
    proxy: { //接口转发
    "/restapi/hkstock": "http://localhost:3009/"
    },
    watchOptions: {
    aggregateTimeout: 300,
    poll: 1000
    },
    }).listen(8099, 'localhost', function (err, result) {
    if (err) console.log(err);
    console.log('Listening at localhost:8099');
    });

    (2)webpack.config.js配置,配置entry、output,同时由于加入hash,index.html中的路径也需要动态改变。因此引入 HtmlWebpackPlugin插件,动态生成一个index.html,修改里面的js路径。

    entry: {
    index: [
    'webpack-dev-server/client?http://localhost:8099', //监听该服务下的变化
    'webpack/hot/only-dev-server',
    './js/index.js'
    ]
    },
    output:{
    path: path.resolve(__dirname, 'build'),
    publicPath: "http://localhost:8099/build/",
    // filename:'[name].min.js',
    filename: '[name].[hash:6].js',
    },
    plugins:[
    //每次打包后index.html中的路径也会自动加上hash值
    new HtmlWebpackPlugin({
    template: path.resolve(__dirname, './index.html'),
    filename:path.resolve(__dirname, './index.build.html'), //js路径替换成带hash的
    hash:true,
    title:"标题"
    }),
    //热加载插件HMR
    new webpack.HotModuleReplacementPlugin(),
    ]


    4、提取公共模块
    参考:https://segmentfault.com/a/1190000011920743

    如果文件是多入口的文件,可能存在,重复代码,把公共代码提取出来,又不会重复下载公共代码了(多个页面间会共享此文件的缓存)。
    对于SPA 应用来说没有特别的需要分离出模块,但是针对首屏渲染速度的提升,可以将某些独立模块分离出来实现按需加载。
    // CommonsChunkPlugin的初始化常用参数有解析?
    // name: 这个给公共代码的chunk唯一的标识
    // filename,如何命名打包后生产的js文件,也是可以用上[name]、[hash]、[chunkhash]
    // minChunks,公共代码的判断标准:某个js模块被多少个chunk加载了才算是公共代码

    new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    filename:'vendor.min.js',
    minChunks: function (module, count) {
    // 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
    )
    }
    }),

    5、代码分割
    单页面应用的公共模块没有必要提取出单独的文件,因为不必考虑复用的情况。但是对于打包生成的文件过大,我们又想分离出几个模块有需要的时候才加载,其实这并不是提取公共模块,而是代码分割,通过:
    new webpack.optimize.CommonsChunkPlugin({
    name: ['生成的项目公共模块文件名', '第三方模块文件名'],
    minChunks: 2,
    }),

    参考:

    https://segmentfault.com/a/1190000006964335

    https://segmentfault.com/a/1190000011920743

  • 相关阅读:
    20165323《Java程序设计》第九周学习总结
    20165323 实验三 敏捷开发与XP实践
    20165323 结对编程之四则运算week2-整体总结
    20165334 20165311 20165329 实验四外设驱动程序设计
    实验四
    20165311 《信息安全系统设计基础》第七周学习
    20165311 《信息安全系统设计基础》第六周学习总结
    20165311 《信息安全系统设计基础》第四周学习总结
    20165311 20165334 20165329实验一 开发环境的熟悉
    2018 第三周 20165311 缓冲区溢出漏洞实验和第三周学习总结
  • 原文地址:https://www.cnblogs.com/lydialee/p/8359374.html
Copyright © 2020-2023  润新知