使用 webpack 导入 angularjs 的最佳实践是啥?

Posted

技术标签:

【中文标题】使用 webpack 导入 angularjs 的最佳实践是啥?【英文标题】:What is the best practice for importing angularjs using webpack?使用 webpack 导入 angularjs 的最佳实践是什么? 【发布时间】:2015-04-23 06:28:28 【问题描述】:

你如何一起使用 Webpack 和 AngularJS,模板加载和资源的按需获取如何?

非常感谢为此目的编写的 webpack.config.js 文件的示例。

此处显示的所有代码 sn-ps 都可以通过this github repo 访问。代码大量改编自this packetloop git repo。

webpack.config.json

var path = require('path');
var ResolverPlugin = require("webpack/lib/ResolverPlugin");

var config = 
  context: __dirname,
  entry: ['webpack/hot/dev-server', './app/app.js'],
  output: 
    path: './build',
    filename: 'bundle.js'
  ,
  module: 
    loaders: [
      test: /\.css$/,
      loader: "style!css-loader"
    , 
      test: /\.scss$/,
      loader: "style!css!sass?outputStyle=expanded"
    , 
      test: /\.jpe?g$|\.gif$|\.png$|\.svg$|\.woff$|\.ttf$/,
      loader: "file"
    , 
      test: /\.html$/,
      loader: "ngtemplate?relativeTo=" + path.join(__dirname, 'app/') + "!raw"
    ]
  ,
  // Let webpack know where the module folders are for bower and node_modules
  // This lets you write things like - require('bower/<plugin>') anywhere in your code base
  resolve: 
    modulesDirectories: ['node_modules', 'lib/bower_components'],
    alias: 
      'npm': __dirname + '/node_modules',
      'vendor': __dirname + '/app/vendor/',
      'bower': __dirname + '/lib/bower_components'
    
  ,
  plugins: [
    // This is to help webpack know that it has to load the js file in bower.json#main
    new ResolverPlugin(
      new ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
    )
  ]
;

module.exports = config;

要将 AngularJS 导入主 app.js,请执行以下操作:

app/vendor/angular.js

'use strict';

if (!global.window.angular) 
  require('bower/angular/angular');

var angular = global.window.angular;
module.exports = angular;

然后像这样在app.js中使用,

app.js

...
var angular = require('vendor/angular');

// Declare app level module
var app = angular.module('myApp', []);

...

下面的说法正确吗?有没有更简单的方法来做到这一点?我看过一些(以任何标准衡量都不是很多)帖子,其中列出了另一种方法。

来自this reddit post comment

// Add to webpack.config.js#module#loaders array
    
      test: /[\/]angular\.js$/,
      loader: "exports?angular"
    

还有另一个插件正在开发中,地址为stackfull/angular-seed。看起来方向是对的,但现在真的很难用。

Webpack 非常棒,但缺乏文档和示例正在扼杀它。

【问题讨论】:

Angular 本身与 webpack 完美开箱即用 - var angular = require('angular')。您还可以要求您的模块在每个模块上具有 name 属性 - var myModule = require('./myModule'); angular.module('foo', [myModule.name])。有一些例外 - ui 路由器是一个值得注意的路由器,它不会导出模块对象,而是导出模块名称本身。 这也是一个不错的起点。它帮助了我。 egghead.io/lessons/angularjs-angular-with-webpack-introduction angular 不能使用以下语法开箱即用:var angular = require('angular') without your app/vendor/angular.js。如果你使用导出加载器并使用 angular,你可以在没有 vendor/angular.js 的情况下让它工作。另请注意,您的依赖项应该是 npm 依赖项。 Bower 依赖项不适用于导出加载程序。 【参考方案1】:

您可以在需要它的所有模块(文件)中只需要 angular。我有一个 github repository 示例如何做到这一点(也使用 webpack 进行构建)。在示例中使用了 ES6 导入语法,但没关系,您可以改用标准的 require()

例子:

import 'bootstrap/dist/css/bootstrap.min.css';
import './app.css';

import bootstrap from 'bootstrap';

import angular from 'angular';
import uirouter from 'angular-ui-router';

import  routing from './app.config';

import common from './common/common.module';

import featureA from './feature-a/feature-a.module';
import featureB from './feature-b/feature-b.module';

const app = angular
    .module('app', [uirouter, common, featureA, featureB])
    .config(routing);

【讨论】:

Angular 模块依赖中不应该是uirouter.name 等吗? 它是这样工作的,看看真实的例子:github.com/tomastrajan/angular-js-es6-testing-example/blob/…【参考方案2】:

我从Angular + FluxWebpack 开始,所以我可以帮助你做一些事情。

基本上我用NPM 安装所有东西,它有module export 系统,所以它什么都没有。 (你可以使用export-loader,但如果你不需要,为什么。)

我的 webpack.config.js 看起来像这样:

var webpack           = require('webpack');
var path              = require('path');
var HtmlWebpackPlugin = require("html-webpack-plugin");

var nodeModulesDir = path.resolve(__dirname, './node_modules');

// Some of my dependencies that I want
// to skip from building in DEV environment
var deps = [
  'angular/angular.min.js',
  ...
];

var config = 
  context: path.resolve(__dirname, './app'),

  entry: ['webpack/hot/dev-server', './main.js'],

  resolve: 
    alias: 
  ,

  output: 
    path: path.resolve(__dirname, './build'),
    filename: 'bundle.js'
  ,

  // This one I am using to define test dependencies
  // directly in the modules
  plugins: [
    new webpack.DefinePlugin(
      ON_TEST: process.env.NODE_ENV === 'test'
    )
  ],

  module: 
    preLoaders: [
      test: /\.coffee$/, loader: "coffeelint", exclude: [nodeModulesDir]
    ],
    loaders: [
      test: /\.js$/, loader: 'ng-annotate', exclude: [nodeModulesDir],
      test: /\.coffee$/, loader: 'coffee', exclude: [nodeModulesDir],
        ...
    ],
    noParse: []
  ,

  devtool: 'source-map'
;

if (process.env.NODE_ENV === 'production') 
  config.entry = 
    app: path.resolve(__dirname, './app/main.js'),
     vendors: ['angular']
  ;
  // config.output.path = path.resolve(__dirname, './dist');
 config.output = 
   path: path.resolve(__dirname, "./dist"),
  filename: "app.[hash].js",
  hash: true
 ;
 config.plugins.push(new webpack.optimize.UglifyJsPlugin());
 config.plugins.push(new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.[hash].js'));
 config.plugins.push(new HtmlWebpackPlugin(
   title: 'myApp',
   template: path.resolve(__dirname, './app/index.html'),
   inject: 'body'
 ));

 delete config.devtool;



  else 
    deps.forEach(function (dep) 
      var depPath = path.resolve(nodeModulesDir, dep);
      config.resolve.alias[dep.split(path.sep)[0]] = depPath;
      config.module.noParse.push(depPath);
    );
  
module.exports = config;

我的 ma​​in.js 看起来像这样:

var angular = require('angular');

if(ON_TEST) 
  require('angular-mocks/angular-mocks');


require('./index.coffee');

并且index.coffee包含主要的角度模块:

ngModule = angular.module 'myApp', []

require('./directive/example.coffee')(ngModule)

【讨论】:

这太不可思议了。恭喜。这段代码是开源的吗?我想看看这个项目,我有 some problems 和 Webpack。 :) @Kamil 你做了那个回购吗?我真的很想看到它。至少,你给我大致展示一下./directive/example.coffee 文件的样子?

以上是关于使用 webpack 导入 angularjs 的最佳实践是啥?的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 模块 + Webpack + ES6 导入 - 依赖注入和连接顺序问题

如何使用 webpack 从 React JS 中的外部 JS 文件导入对象

AngularJS 和 Webpack 集成

使用 Typescript 和 Webpack 管理依赖项的 AngularJS

AngularJS- 使用 LazyLoad- Webpack 动态加载脚本文件

无法使用 webpack 在依赖项上加载 angularjs $templateCache 模板